diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:30 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 15:54:30 +0000 |
commit | deae12c6b683898f5213992d561a59d4ea889cca (patch) | |
tree | 3ed14c7b76f47ec80c1868c34bd0e5de385db618 /src/xcms |
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'src/xcms')
65 files changed, 16424 insertions, 0 deletions
diff --git a/src/xcms/AddDIC.c b/src/xcms/AddDIC.c new file mode 100644 index 0000000..aefae0f --- /dev/null +++ b/src/xcms/AddDIC.c @@ -0,0 +1,156 @@ +/* $Xorg: AddDIC.c,v 1.3 2000/08/17 19:44:29 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsAddDIC.c + * + * DESCRIPTION + * Source for XcmsAddColorSpace + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/* + * DEFINES + */ +#define NextUnregDiCsID(lastid) \ + (XCMS_UNREG_ID(lastid) ? ++lastid : XCMS_FIRST_UNREG_DI_ID) +#define MAX(x,y) ((x) < (y) ? (y) : (x)) + + +/* + * EXTERNS + */ +extern XcmsPerDpyInfo *_XcmsFindDpyInfo(); +extern XPointer *_XcmsPushPointerArray(); +extern XcmsColorFormat _XcmsRegFormatOfPrefix(); +extern XcmsColorSpace **_XcmsDIColorSpaces; +extern XcmsColorSpace *_XcmsDIColorSpacesInit[]; + +/* + * NAME + * XcmsAddColorSpace - Add a Device-Independent Color Space + * + * SYNOPSIS + */ +Status +XcmsAddColorSpace(pCS) + XcmsColorSpace *pCS; +/* + * DESCRIPTION + * DI Color Spaces are managed on a global basis. + * This means that with exception of the provided DI color spaces: + * CIEXYZ, CIExyY, CIELab, CIEuvY, CIELuv, and TekHVC + * DI color spaces may have different XcmsColorFormat IDs between + * clients. So, you must be careful when using XcmsColor + * structures between clients! Use the routines XcmsFormatOfPrefix() + * and XcmsPrefixOfFormat() appropriately. + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure + */ +{ + XcmsColorSpace **papColorSpaces; + XcmsColorSpace *ptmpCS; + XcmsColorFormat lastID = 0; + + if ((pCS->id = _XcmsRegFormatOfPrefix(pCS->prefix)) != 0) { + if (XCMS_DD_ID(pCS->id)) { + /* This is a Device-Dependent Color Space */ + return(XcmsFailure); + } + /* + * REGISTERED DI Color Space + * then see if the color space has already been added to the + * system: + * a. If the same ID/prefix and same XcmsColorSpec is found, + * then its a duplicate, so return success. + * b. If same ID/prefix but different XcmsColorSpec is + * found, then add the color space to the front of the + * list using the same ID. This allows one to override + * an existing DI Color Space. + * c. Otherwise none found so just add the color space. + */ + if ((papColorSpaces = _XcmsDIColorSpaces) != NULL) { + while ((ptmpCS = *papColorSpaces++) != NULL) { + if (pCS->id == ptmpCS->id) { + if (pCS == ptmpCS) { + /* a. duplicate*/ + return(XcmsSuccess); + } + /* b. same ID/prefix but different XcmsColorSpace */ + break; + } + } + } + /* c. None found */ + } else { + /* + * UNREGISTERED DI Color Space + * then see if the color space has already been added to the + * system: + * a. If same prefix and XcmsColorSpec, then + * its a duplicate ... return success. + * b. If same prefix but different XcmsColorSpec, then + * add the color space to the front of the list using + * the same ID. This allows one to override an existing + * DI Color Space. + * c. Otherwise none found so, add the color space using the + * next unregistered ID for the connection. + */ + if ((papColorSpaces = _XcmsDIColorSpaces) != NULL) { + while ((ptmpCS = *papColorSpaces++) != NULL) { + lastID = MAX(lastID, ptmpCS->id); + if (strcmp(pCS->prefix, ptmpCS->prefix) == 0) { + if (pCS == ptmpCS) { + /* a. duplicate */ + return(XcmsSuccess); + } + /* b. same prefix but different XcmsColorSpec */ + pCS->id = ptmpCS->id; + goto AddColorSpace; + } + } + } + /* c. None found */ + pCS->id = NextUnregDiCsID(lastID); + } + + +AddColorSpace: + if ((papColorSpaces = (XcmsColorSpace **) + _XcmsPushPointerArray((XPointer *)_XcmsDIColorSpaces, + (XPointer)pCS, + (XPointer *)_XcmsDIColorSpacesInit)) == NULL) { + return(XcmsFailure); + } + _XcmsDIColorSpaces = papColorSpaces; + return(XcmsSuccess); +} diff --git a/src/xcms/AddSF.c b/src/xcms/AddSF.c new file mode 100644 index 0000000..5c2ae54 --- /dev/null +++ b/src/xcms/AddSF.c @@ -0,0 +1,155 @@ +/* $Xorg: AddSF.c,v 1.3 2000/08/17 19:44:29 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsAddSF.c + * + * DESCRIPTION + * Source for XcmsAddFunctionSet + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define NextUnregDdCsID(lastid) \ + (XCMS_UNREG_ID(lastid) ? ++lastid : XCMS_FIRST_UNREG_DD_ID) +#define MIN(x,y) ((x) > (y) ? (y) : (x)) + + +/* + * EXTERNS + */ +extern XPointer *_XcmsPushPointerArray(); +extern XcmsColorFormat _XcmsRegFormatOfPrefix(); +extern XcmsFunctionSet **_XcmsSCCFuncSets; +extern XcmsFunctionSet **_XcmsSCCFuncSetsInit; +extern XcmsColorSpace **_XcmsDDColorSpaces; +extern XcmsColorSpace **_XcmsDDColorSpacesInit; + + + +/* + * NAME + * XcmsAddFunctionSet - Add an Screen Color Characterization + * Function Set + * + * SYNOPSIS + */ +Status +XcmsAddFunctionSet(pNewFS) + XcmsFunctionSet *pNewFS; +/* + * DESCRIPTION + * Additional Screen Color Characterization Function Sets are + * managed on a global basis. This means that with exception + * of the provided DD color spaces: + * RGB and RGBi + * DD color spaces may have different XcmsColorFormat IDs between + * clients. So, you must be careful when using XcmsColorFormat + * across clients! Use the routines XcmsFormatOfPrefix() + * and XcmsPrefixOfFormat() appropriately. + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure + * + * CAVEATS + * Additional Screen Color Characterization Function Sets + * should be added prior to any use of the routine + * XcmsCreateCCC(). If not, XcmsCCC structures created + * prior to the call of this routines will not have had + * a chance to initialize using the added Screen Color + * Characterization Function Set. + */ +{ + XcmsFunctionSet **papSCCFuncSets = _XcmsSCCFuncSets; + XcmsColorSpace **papNewCSs; + XcmsColorSpace *pNewCS, **paptmpCS; + XcmsColorFormat lastID = 0; + + + if (papSCCFuncSets != NULL) { + if ((papNewCSs = pNewFS->DDColorSpaces) == NULL) { + /* + * Error, new Screen Color Characterization Function Set + * missing color spaces + */ + return(XcmsFailure); + } + while ((pNewCS = *papNewCSs++) != NULL) { + if ((pNewCS->id = _XcmsRegFormatOfPrefix(pNewCS->prefix)) != 0) { + if (XCMS_DI_ID(pNewCS->id)) { + /* This is a Device-Independent Color Space */ + return(XcmsFailure); + } + /* + * REGISTERED DD Color Space + * therefore use the registered ID. + */ + } else { + /* + * UNREGISTERED DD Color Space + * then see if the color space is already in + * _XcmsDDColorSpaces. + * a. If same prefix, then use the same ID. + * b. Otherwise, use a new ID. + */ + for (paptmpCS = _XcmsDDColorSpaces; *paptmpCS != NULL; + paptmpCS++){ + lastID = MIN(lastID, (*paptmpCS)->id); + if (strcmp(pNewCS->prefix, (*paptmpCS)->prefix) == 0) { + pNewCS->id = (*paptmpCS)->id; + break; + } + } + if (pNewCS->id == 0) { + /* still haven't found one */ + pNewCS->id = NextUnregDdCsID(lastID); + if ((paptmpCS = (XcmsColorSpace **)_XcmsPushPointerArray( + (XPointer *) _XcmsDDColorSpaces, + (XPointer) pNewCS, + (XPointer *) _XcmsDDColorSpacesInit)) == NULL) { + return(XcmsFailure); + } + _XcmsDDColorSpaces = paptmpCS; + } + } + } + } + if ((papSCCFuncSets = (XcmsFunctionSet **) + _XcmsPushPointerArray((XPointer *) _XcmsSCCFuncSets, + (XPointer) pNewFS, + (XPointer *)_XcmsSCCFuncSetsInit)) == NULL) { + return(XcmsFailure); + } + _XcmsSCCFuncSets = papSCCFuncSets; + + return(XcmsSuccess); +} diff --git a/src/xcms/CCC.c b/src/xcms/CCC.c new file mode 100644 index 0000000..9a7d516 --- /dev/null +++ b/src/xcms/CCC.c @@ -0,0 +1,287 @@ +/* $Xorg: CCC.c,v 1.4 2001/02/09 02:03:31 xorgcvs Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsCCC.c - Color Conversion Context Routines + * + * DESCRIPTION + * Routines to create, access, and free Color Conversion + * Context structures. + * + * + */ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#include <stdio.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +extern XcmsIntensityMap *_XcmsGetIntensityMap(); + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCreateCCC + * + * SYNOPSIS + */ + +XcmsCCC +XcmsCreateCCC(dpy, screenNumber, visual, clientWhitePt, gamutCompProc, + gamutCompClientData, whitePtAdjProc, whitePtAdjClientData) + Display *dpy; + int screenNumber; + Visual *visual; + XcmsColor *clientWhitePt; + XcmsCompressionProc gamutCompProc; + XPointer gamutCompClientData; + XcmsWhiteAdjustProc whitePtAdjProc; + XPointer whitePtAdjClientData; +/* + * DESCRIPTION + * Given a Display, Screen, Visual, etc., this routine creates + * an appropriate Color Conversion Context. + * + * RETURNS + * Returns NULL if failed; otherwise address of the newly + * created XcmsCCC. + * + */ +{ + XcmsCCC pDefaultCCC = XcmsDefaultCCC(dpy, screenNumber); + XcmsCCC newccc; + XcmsIntensityMap *pIMap; + XcmsPerScrnInfo *pNewScrnInfo; + + if (pDefaultCCC == NULL || + !(newccc = (XcmsCCC) Xcalloc(1, (unsigned) sizeof(XcmsCCCRec)))) { + return(NULL); + } + + /* + * Should inherit the following as result of a memmove(): + * dpy + * screenNumber + * pPerScrnInfo + */ + memcpy((char *)newccc, (char *)pDefaultCCC, sizeof(XcmsCCCRec)); + if (clientWhitePt) { + memcpy((char *)&newccc->clientWhitePt, (char *)clientWhitePt, + sizeof(XcmsColor)); + } + if (gamutCompProc) { + newccc->gamutCompProc = gamutCompProc; + } + if (gamutCompClientData) { + newccc->gamutCompClientData = gamutCompClientData; + } + if (whitePtAdjProc) { + newccc->whitePtAdjProc = whitePtAdjProc; + } + if (whitePtAdjClientData) { + newccc->whitePtAdjClientData = whitePtAdjClientData; + } + + /* + * Now check our list of per-Visual Intensity tables. + * If one exists replace the pPerScrnInfo. + */ + if ((pIMap = _XcmsGetIntensityMap(dpy, visual)) != NULL) { + if (!(pNewScrnInfo = (XcmsPerScrnInfo *) + Xcalloc(1, (unsigned) sizeof(XcmsPerScrnInfo)))) { + Xfree(newccc); + return(NULL); + } + memcpy((char *)pNewScrnInfo, (char *)newccc->pPerScrnInfo, + sizeof(XcmsPerScrnInfo)); + pNewScrnInfo->screenData = pIMap->screenData; + newccc->pPerScrnInfo = pNewScrnInfo; + } + + /* + * Set visual component + */ + newccc->visual = visual; + + return(newccc); +} + + +/* + * NAME + * XcmsDefaultCCC + * + * SYNOPSIS + */ +XcmsCCC +XcmsDefaultCCC(dpy, screenNumber) + Display *dpy; + int screenNumber; +/* + * DESCRIPTION + * Given a Display and Screen, this routine creates + * returns the Screen's default Color Conversion Context. + * Note that a Screen's default CCC is built with the + * screen default visual. + * + * RETURNS + * Returns NULL if failed; otherwise address of the + * XcmsCCC for the Screen's default CCC. + * + */ +{ + XcmsCCC ccc; + + + if ((screenNumber < 0) || (screenNumber >= ScreenCount(dpy))) { + return((XcmsCCC)NULL); + } + + /* + * Check if the XcmsCCC's for each screen has been created + */ + if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) { + if (!_XcmsInitDefaultCCCs(dpy)) { + return((XcmsCCC)NULL); + } + } + + ccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber; + + if (!ccc->pPerScrnInfo) { + /* + * Need to create the XcmsPerScrnInfo structure. The + * _XcmsInitScrnInfo routine will create the XcmsPerScrnInfo + * structure as well as initialize its functionSet and pScreenData + * components. + */ + if (!_XcmsInitScrnInfo(dpy, screenNumber)) { + return((XcmsCCC)NULL); + } + return(ccc); + } else { + /* + * If ccc->pPerScrnInfo->state == XcmsInitSuccess, + * then the pPerScrnInfo component has already been initialized + * therefore, just return ccc. + * If ccc->pPerScrnInfo->state == XcmsInitFailure, + * then this means that we already attempted to initialize + * the pPerScrnInfo component but failed therefore stuffing + * the pPerScrnInfo component with defaults. Just return ccc. + * If ccc->pPerScrnInfo->state == XcmsInitNone, + * then attempt to initialize the pPerScrnInfo component. + */ + switch (ccc->pPerScrnInfo->state) { + case XcmsInitFailure : + /* fall through */ + case XcmsInitSuccess : + return(ccc); + case XcmsInitNone : + /* XcmsPerScreenInfo has not been initialized */ + if (!_XcmsInitScrnInfo(dpy, screenNumber)) { + return((XcmsCCC)NULL); + } + return(ccc); + default : + return((XcmsCCC)NULL); + } + } +} + + +/* + * NAME + * XcmsFreeCCC + * + * SYNOPSIS + */ +void +XcmsFreeCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Frees memory associated with a Color Conversion Context + * that was created with XcmsCreateCCC(). + * + * RETURNS + * void + * + */ +{ + if (ccc->dpy->cms.defaultCCCs && + ccc == ((XcmsCCC)ccc->dpy->cms.defaultCCCs) + ccc->screenNumber) { + /* do not allow clients to free DefaultCCC's */ + return; + } + + /* + * Note that XcmsPerScrnInfo sub-structures are freed here only if + * they are for visuals that have per-Visual intensity tables. + * Otherwise the XcmsPerScrnInfo structure is being shared! + * For the latter, there is only one allocated per Screen and it just + * so happens * that we place its initial reference is placed in the + * default CCC. The routine _XcmsFreeDefaultCCCs frees them. + */ + if (_XcmsGetIntensityMap(ccc->dpy, ccc->visual) != NULL) { + Xfree(ccc->pPerScrnInfo); + } + + Xfree(ccc); +} diff --git a/src/xcms/CvColW.c b/src/xcms/CvColW.c new file mode 100644 index 0000000..249e30e --- /dev/null +++ b/src/xcms/CvColW.c @@ -0,0 +1,139 @@ +/* $Xorg: CvColW.c,v 1.3 2000/08/17 19:44:32 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * XcmsCvColW.c + * + * DESCRIPTION + * <overall description of what the package does> + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + + +/* + * NAME + * _XcmsConvertColorsWithWhitePt - Convert XcmsColor structures + * + * SYNOPSIS + */ +Status +_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePt, nColors, + newFormat, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + XcmsColor *pWhitePt; + unsigned int nColors; + XcmsColorFormat newFormat; + Bool *pCompressed; +/* + * DESCRIPTION + * Convert XcmsColor structures between device-independent + * and/or device-dependent formats but allowing the calling + * routine to specify the white point to be associated + * with the color specifications (overriding + * ccc->clientWhitePt). + * + * This routine has been provided for use in white point + * adjustment routines. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression, + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + * + */ +{ + if (ccc == NULL || pColors_in_out == NULL || + pColors_in_out->format == XcmsUndefinedFormat) { + return(XcmsFailure); + } + + if (nColors == 0 || pColors_in_out->format == newFormat) { + /* do nothing */ + return(XcmsSuccess); + } + + if (XCMS_DI_ID(pColors_in_out->format) && XCMS_DI_ID(newFormat)) { + /* + * Device-Independent to Device-Independent Conversion + */ + return(_XcmsDIConvertColors(ccc, pColors_in_out, pWhitePt, nColors, + newFormat)); + } + if (XCMS_DD_ID(pColors_in_out->format) && XCMS_DD_ID(newFormat)) { + /* + * Device-Dependent to Device-Dependent Conversion + */ + return(_XcmsDDConvertColors(ccc, pColors_in_out, nColors, newFormat, + pCompressed)); + } + + /* + * Otherwise we have: + * 1. Device-Independent to Device-Dependent Conversion + * OR + * 2. Device-Dependent to Device-Independent Conversion + */ + + if (XCMS_DI_ID(pColors_in_out->format)) { + /* + * 1. Device-Independent to Device-Dependent Conversion + */ + /* First convert to CIEXYZ */ + if (_XcmsDIConvertColors(ccc, pColors_in_out, pWhitePt, nColors, + XcmsCIEXYZFormat) == XcmsFailure) { + return(XcmsFailure); + } + /* Then convert to DD Format */ + return(_XcmsDDConvertColors(ccc, pColors_in_out, nColors, newFormat, + pCompressed)); + } else { + /* + * 2. Device-Dependent to Device-Independent Conversion + */ + /* First convert to CIEXYZ */ + if (_XcmsDDConvertColors(ccc, pColors_in_out, nColors, + XcmsCIEXYZFormat, pCompressed) == XcmsFailure) { + return(XcmsFailure); + } + /* Then convert to DI Format */ + return(_XcmsDIConvertColors(ccc, pColors_in_out, pWhitePt, nColors, + newFormat)); + } +} diff --git a/src/xcms/CvCols.c b/src/xcms/CvCols.c new file mode 100644 index 0000000..d74ea32 --- /dev/null +++ b/src/xcms/CvCols.c @@ -0,0 +1,1048 @@ +/* $Xorg: CvCols.c,v 1.3 2000/08/17 19:44:32 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsCvCols.c + * + * DESCRIPTION + * Xcms API routine that converts between the + * device-independent color spaces. + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + * External declarations required locally to this package + * that are not already declared in any of the included header + * files (external includes or internal includes). + */ +extern XcmsRegColorSpaceEntry _XcmsRegColorSpaces[]; +extern XcmsColorSpace **_XcmsDIColorSpaces; +extern XcmsColorSpace **_XcmsDDColorSpaces; + +/* + * LOCAL DEFINES + */ +#define DD_FORMAT 0x01 +#define DI_FORMAT 0x02 +#define MIX_FORMAT 0x04 +#ifndef MAX +# define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + +/* + * FORWARD DECLARATIONS + */ +Status _XcmsDIConvertColors(); +Status _XcmsDDConvertColors(); + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * EqualCIEXYZ + * + * SYNOPSIS + */ +static int +EqualCIEXYZ(p1, p2) + XcmsColor *p1, *p2; +/* + * DESCRIPTION + * Compares two XcmsColor structures that are in XcmsCIEXYZFormat + * + * RETURNS + * Returns 1 if equal; 0 otherwise. + * + */ +{ + if (p1->format != XcmsCIEXYZFormat || p2->format != XcmsCIEXYZFormat) { + return(0); + } + if ((p1->spec.CIEXYZ.X != p2->spec.CIEXYZ.X) + || (p1->spec.CIEXYZ.Y != p2->spec.CIEXYZ.Y) + || (p1->spec.CIEXYZ.Z != p2->spec.CIEXYZ.Z)) { + return(0); + } + return(1); +} + + +/* + * NAME + * XcmsColorSpace + * + * SYNOPSIS + */ +static XcmsColorSpace * +ColorSpaceOfID(ccc, id) + XcmsCCC ccc; + XcmsColorFormat id; +/* + * DESCRIPTION + * Returns a pointer to the color space structure + * (XcmsColorSpace) associated with the specified color space + * ID. + * + * RETURNS + * Pointer to matching XcmsColorSpace structure if found; + * otherwise NULL. + */ +{ + XcmsColorSpace **papColorSpaces; + + if (ccc == NULL) { + return(NULL); + } + + /* + * First try Device-Independent color spaces + */ + papColorSpaces = _XcmsDIColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + return(*papColorSpaces); + } + papColorSpaces++; + } + } + + /* + * Next try Device-Dependent color spaces + */ + papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + return(*papColorSpaces); + } + papColorSpaces++; + } + } + + return(NULL); +} + + +/* + * NAME + * ValidDIColorSpaceID + * + * SYNOPSIS + */ +static int +ValidDIColorSpaceID(id) + XcmsColorFormat id; +/* + * DESCRIPTION + * Determines if the specified color space ID is a valid + * Device-Independent color space in the specified Color + * Conversion Context. + * + * RETURNS + * Returns zero if not valid; otherwise non-zero. + */ +{ + XcmsColorSpace **papRec; + papRec = _XcmsDIColorSpaces; + if (papRec != NULL) { + while (*papRec != NULL) { + if ((*papRec)->id == id) { + return(1); + } + papRec++; + } + } + return(0); +} + + +/* + * NAME + * ValidDDColorSpaceID + * + * SYNOPSIS + */ +static int +ValidDDColorSpaceID(ccc, id) + XcmsCCC ccc; + XcmsColorFormat id; +/* + * DESCRIPTION + * Determines if the specified color space ID is a valid + * Device-Dependent color space in the specified Color + * Conversion Context. + * + * RETURNS + * Returns zero if not valid; otherwise non-zero. + */ +{ + XcmsColorSpace **papRec; + + if (ccc->pPerScrnInfo->state != XcmsInitNone) { + papRec = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces; + while (*papRec != NULL) { + if ((*papRec)->id == id) { + return(1); + } + papRec++; + } + } + return(0); +} + + +/* + * NAME + * ConvertMixedColors - Convert XcmsColor structures + * + * SYNOPSIS + */ +static Status +ConvertMixedColors(ccc, pColors_in_out, pWhitePt, nColors, + targetFormat, format_flag) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + XcmsColor *pWhitePt; + unsigned int nColors; + XcmsColorFormat targetFormat; + unsigned char format_flag; +/* + * DESCRIPTION + * This routine will only convert the following types of + * batches: + * DI to DI + * DD to DD + * DD to CIEXYZ + * In other words, it will not convert the following types of + * batches: + * DI to DD + * DD to DI(not CIEXYZ) + * + * format_flag: + * 0x01 : convert Device-Dependent only specifications to the + * target format. + * 0x02 : convert Device-Independent only specifications to the + * target format. + * 0x03 : convert all specifications to the target format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if none of the color specifications were + * compressed in the conversion process + * XcmsSuccessWithCompression if at least one of the + * color specifications were compressed in the + * conversion process. + * + */ +{ + XcmsColor *pColor, *pColors_start; + XcmsColorFormat format; + Status retval_tmp; + Status retval = XcmsSuccess; + unsigned int iColors; + unsigned int nBatch; + + /* + * Convert array of mixed color specifications in batches of + * contiguous formats to the target format + */ + iColors = 0; + while (iColors < nColors) { + /* + * Find contiguous array of color specifications with the + * same format + */ + pColor = pColors_start = pColors_in_out + iColors; + format = pColors_start->format; + nBatch = 0; + while (iColors < nColors && pColor->format == format) { + pColor++; + nBatch++; + iColors++; + } + if (format != targetFormat) { + /* + * Need to convert this batch from current format to target format. + */ + if (XCMS_DI_ID(format) && (format_flag & DI_FORMAT) && + XCMS_DI_ID(targetFormat)) { + /* + * DI->DI + * + * Format of interest is Device-Independent, + * This batch contains Device-Independent specifications, and + * the Target format is Device-Independent. + */ + retval_tmp = _XcmsDIConvertColors(ccc, pColors_start, pWhitePt, + nBatch, targetFormat); + } else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) && + (targetFormat == XcmsCIEXYZFormat)) { + /* + * DD->CIEXYZ + * + * Format of interest is Device-Dependent, + * This batch contains Device-Dependent specifications, and + * the Target format is CIEXYZ. + * + * Since DD->CIEXYZ we can use NULL instead of pCompressed. + */ + if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc, + pWhitePt, ScreenWhitePointOfCCC(ccc))) { + /* + * Need to call WhiteAdjustProc (Screen White Point to + * White Point). + */ + retval_tmp = (*ccc->whitePtAdjProc)(ccc, + ScreenWhitePointOfCCC(ccc), pWhitePt, + XcmsCIEXYZFormat, pColors_start, nBatch, + (Bool *)NULL); + } else { + retval_tmp = _XcmsDDConvertColors(ccc, pColors_start, + nBatch, XcmsCIEXYZFormat, (Bool *)NULL); + } + } else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) && + XCMS_DD_ID(targetFormat)) { + /* + * DD->DD(not CIEXYZ) + * + * Format of interest is Device-Dependent, + * This batch contains Device-Dependent specifications, and + * the Target format is Device-Dependent and not CIEXYZ. + */ + retval_tmp = _XcmsDDConvertColors(ccc, pColors_start, nBatch, + targetFormat, (Bool *)NULL); + } else { + /* + * This routine is called for the wrong reason. + */ + return(XcmsFailure); + } + if (retval_tmp == XcmsFailure) { + return(XcmsFailure); + } + retval = MAX(retval, retval_tmp); + } + } + return(retval); +} + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsEqualWhitePts + * + * SYNOPSIS + */ +int +_XcmsEqualWhitePts(ccc, pWhitePt1, pWhitePt2) + XcmsCCC ccc; + XcmsColor *pWhitePt1, *pWhitePt2; +/* + * DESCRIPTION + * + * RETURNS + * Returns 0 if not equal; otherwise 1. + * + */ +{ + XcmsColor tmp1, tmp2; + + memcpy((char *)&tmp1, (char *)pWhitePt1, sizeof(XcmsColor)); + memcpy((char *)&tmp2, (char *)pWhitePt2, sizeof(XcmsColor)); + + if (tmp1.format != XcmsCIEXYZFormat) { + if (_XcmsDIConvertColors(ccc, &tmp1, (XcmsColor *) NULL, 1, + XcmsCIEXYZFormat)==0) { + return(0); + } + } + + if (tmp2.format != XcmsCIEXYZFormat) { + if (_XcmsDIConvertColors(ccc, &tmp2, (XcmsColor *) NULL, 1, + XcmsCIEXYZFormat)==0) { + return(0); + } + } + + return (EqualCIEXYZ(&tmp1, &tmp2)); +} + + +/* + * NAME + * _XcmsDIConvertColors - Convert XcmsColor structures + * + * SYNOPSIS + */ +Status +_XcmsDIConvertColors(ccc, pColors_in_out, pWhitePt, nColors, + newFormat) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + XcmsColor *pWhitePt; + unsigned int nColors; + XcmsColorFormat newFormat; +/* + * DESCRIPTION + * Convert XcmsColor structures to another Device-Independent + * form. + * + * Here are some assumptions that this routine makes: + * 1. The calling routine has already checked if + * pColors_in_out->format == newFormat, therefore + * there is no need to check again here. + * 2. The calling routine has already checked nColors, + * therefore this routine assumes nColors > 0. + * 3. The calling routine may want to convert only between + * CIExyY <-> CIEXYZ <-> CIEuvY + * therefore, this routine allows pWhitePt to equal NULL. + * + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsColorSpace *pFrom, *pTo; + XcmsConversionProc *src_to_CIEXYZ, *src_from_CIEXYZ; + XcmsConversionProc *dest_to_CIEXYZ, *dest_from_CIEXYZ; + XcmsConversionProc *to_CIEXYZ_stop, *from_CIEXYZ_start; + XcmsConversionProc *tmp; + + /* + * Allow pWhitePt to equal NULL. This appropriate when converting + * anywhere between: + * CIExyY <-> CIEXYZ <-> CIEuvY + */ + + if (pColors_in_out == NULL || + !ValidDIColorSpaceID(pColors_in_out->format) || + !ValidDIColorSpaceID(newFormat)) { + return(XcmsFailure); + } + + /* + * Get a handle on the function list for the current specification format + */ + if ((pFrom = ColorSpaceOfID(ccc, pColors_in_out->format)) + == NULL) { + return(XcmsFailure); + } + + /* + * Get a handle on the function list for the new specification format + */ + if ((pTo = ColorSpaceOfID(ccc, newFormat)) == NULL) { + return(XcmsFailure); + } + + src_to_CIEXYZ = pFrom->to_CIEXYZ; + src_from_CIEXYZ = pFrom->from_CIEXYZ; + dest_to_CIEXYZ = pTo->to_CIEXYZ; + dest_from_CIEXYZ = pTo->from_CIEXYZ; + + if (pTo->inverse_flag && pFrom->inverse_flag) { + /* + * Find common function pointers + */ + for (to_CIEXYZ_stop = src_to_CIEXYZ; *to_CIEXYZ_stop; to_CIEXYZ_stop++){ + for (tmp = dest_to_CIEXYZ; *tmp; tmp++) { + if (*to_CIEXYZ_stop == *tmp) { + goto Continue; + } + } + } + +Continue: + + /* + * Execute the functions to CIEXYZ, stopping short as necessary + */ + while (src_to_CIEXYZ != to_CIEXYZ_stop) { + if ((*src_to_CIEXYZ++)(ccc, pWhitePt, pColors_in_out, + nColors) == XcmsFailure) { + return(XcmsFailure); + } + } + + /* + * Determine where to start on the from_CIEXYZ path. + */ + from_CIEXYZ_start = dest_from_CIEXYZ; + tmp = src_from_CIEXYZ; + while ((*from_CIEXYZ_start == *tmp) && (*from_CIEXYZ_start != NULL)) { + from_CIEXYZ_start++; + tmp++; + } + + } else { + /* + * The function in at least one of the Color Spaces are not + * complementary, i.e., + * for an i, 0 <= i < n elements + * from_CIEXYZ[i] is not the inverse of to_CIEXYZ[i] + * + * Execute the functions all the way to CIEXYZ + */ + while (*src_to_CIEXYZ) { + if ((*src_to_CIEXYZ++)(ccc, pWhitePt, pColors_in_out, + nColors) == XcmsFailure) { + return(XcmsFailure); + } + } + + /* + * Determine where to start on the from_CIEXYZ path. + */ + from_CIEXYZ_start = dest_from_CIEXYZ; + } + + + /* + * Execute the functions from CIEXYZ. + */ + while (*from_CIEXYZ_start) { + if ((*from_CIEXYZ_start++)(ccc, pWhitePt, pColors_in_out, + nColors) == XcmsFailure) { + return(XcmsFailure); + } + } + + return(XcmsSuccess); +} + + +/* + * NAME + * _XcmsDDConvertColors - Convert XcmsColor structures + * + * SYNOPSIS + */ +Status +_XcmsDDConvertColors(ccc, pColors_in_out, nColors, newFormat, + pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + XcmsColorFormat newFormat; + Bool *pCompressed; +/* + * DESCRIPTION + * Convert XcmsColor structures: + * + * 1. From CIEXYZ to Device-Dependent formats (typically RGB and + * RGBi), + * or + * 2. Between Device-Dependent formats (typically RGB and RGBi). + * + * Assumes that these specifications have already been white point + * adjusted if necessary from Client White Point to Screen + * White Point. Therefore, the white point now associated + * with the specifications is the Screen White Point. + * + * pCompressed may be NULL. If so this indicates that the + * calling routine is not interested in knowing exactly which + * color was compressed, if any. + * + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if none of the color specifications were + * compressed in the conversion process + * XcmsSuccessWithCompression if at least one of the + * color specifications were compressed in the + * conversion process. + * + */ +{ + XcmsColorSpace *pFrom, *pTo; + XcmsConversionProc *src_to_CIEXYZ, *src_from_CIEXYZ; + XcmsConversionProc *dest_to_CIEXYZ, *dest_from_CIEXYZ; + XcmsConversionProc *from_CIEXYZ_start, *to_CIEXYZ_stop; + XcmsConversionProc *tmp; + int retval; + int hasCompressed = 0; + + if (ccc == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + if (nColors == 0 || pColors_in_out->format == newFormat) { + /* do nothing */ + return(XcmsSuccess); + } + + if (((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet) == NULL) { + return(XcmsFailure); /* hmm, an internal error? */ + } + + /* + * Its ok if pColors_in_out->format == XcmsCIEXYZFormat + * or + * if newFormat == XcmsCIEXYZFormat + */ + if ( !( ValidDDColorSpaceID(ccc, pColors_in_out->format) + || + (pColors_in_out->format == XcmsCIEXYZFormat)) + || + !(ValidDDColorSpaceID(ccc, newFormat) + || + newFormat == XcmsCIEXYZFormat)) { + return(XcmsFailure); + } + + if ((pFrom = ColorSpaceOfID(ccc, pColors_in_out->format)) == NULL){ + return(XcmsFailure); + } + + if ((pTo = ColorSpaceOfID(ccc, newFormat)) == NULL) { + return(XcmsFailure); + } + + src_to_CIEXYZ = pFrom->to_CIEXYZ; + src_from_CIEXYZ = pFrom->from_CIEXYZ; + dest_to_CIEXYZ = pTo->to_CIEXYZ; + dest_from_CIEXYZ = pTo->from_CIEXYZ; + + if (pTo->inverse_flag && pFrom->inverse_flag) { + /* + * Find common function pointers + */ + for (to_CIEXYZ_stop = src_to_CIEXYZ; *to_CIEXYZ_stop; to_CIEXYZ_stop++){ + for (tmp = dest_to_CIEXYZ; *tmp; tmp++) { + if (*to_CIEXYZ_stop == *tmp) { + goto Continue; + } + } + } +Continue: + + /* + * Execute the functions + */ + while (src_to_CIEXYZ != to_CIEXYZ_stop) { + retval = (*src_to_CIEXYZ++)(ccc, pColors_in_out, nColors, + pCompressed); + if (retval == XcmsFailure) { + return(XcmsFailure); + } + hasCompressed |= (retval == XcmsSuccessWithCompression); + } + + /* + * Determine where to start on the from_CIEXYZ path. + */ + from_CIEXYZ_start = dest_from_CIEXYZ; + tmp = src_from_CIEXYZ; + while ((*from_CIEXYZ_start == *tmp) && (*from_CIEXYZ_start != NULL)) { + from_CIEXYZ_start++; + tmp++; + } + + } else { + /* + * The function in at least one of the Color Spaces are not + * complementary, i.e., + * for an i, 0 <= i < n elements + * from_CIEXYZ[i] is not the inverse of to_CIEXYZ[i] + * + * Execute the functions all the way to CIEXYZ + */ + while (*src_to_CIEXYZ) { + retval = (*src_to_CIEXYZ++)(ccc, pColors_in_out, nColors, + pCompressed); + if (retval == XcmsFailure) { + return(XcmsFailure); + } + hasCompressed |= (retval == XcmsSuccessWithCompression); + } + + /* + * Determine where to start on the from_CIEXYZ path. + */ + from_CIEXYZ_start = dest_from_CIEXYZ; + } + + while (*from_CIEXYZ_start) { + retval = (*from_CIEXYZ_start++)(ccc, pColors_in_out, nColors, + pCompressed); + if (retval == XcmsFailure) { + return(XcmsFailure); + } + hasCompressed |= (retval == XcmsSuccessWithCompression); + } + + return(hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsConvertColors - Convert XcmsColor structures + * + * SYNOPSIS + */ +Status +XcmsConvertColors(ccc, pColors_in_out, nColors, targetFormat, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + XcmsColorFormat targetFormat; + Bool *pCompressed; +/* + * DESCRIPTION + * Convert XcmsColor structures to another format + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression, + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + * + */ +{ + XcmsColor clientWhitePt; + XcmsColor Color1; + XcmsColor *pColors_tmp; + int callWhiteAdjustProc = 0; + XcmsColorFormat format; + Status retval; + unsigned char contents_flag = 0x00; + unsigned int iColors; + + if (ccc == NULL || pColors_in_out == NULL || + !(ValidDIColorSpaceID(targetFormat) || + ValidDDColorSpaceID(ccc, targetFormat))) { + return(XcmsFailure); + } + + /* + * Check formats in color specification array + */ + format = pColors_in_out->format; + for (pColors_tmp = pColors_in_out, iColors = nColors; iColors; pColors_tmp++, iColors--) { + if (!(ValidDIColorSpaceID(pColors_tmp->format) || + ValidDDColorSpaceID(ccc, pColors_tmp->format))) { + return(XcmsFailure); + } + if (XCMS_DI_ID(pColors_tmp->format)) { + contents_flag |= DI_FORMAT; + } else { + contents_flag |= DD_FORMAT; + } + if (pColors_tmp->format != format) { + contents_flag |= MIX_FORMAT; + } + } + + /* + * Check if we need the Client White Point. + */ + if ((contents_flag & DI_FORMAT) || XCMS_DI_ID(targetFormat)) { + /* To proceed, we need to get the Client White Point */ + memcpy((char *)&clientWhitePt, (char *)&ccc->clientWhitePt, + sizeof(XcmsColor)); + if (clientWhitePt.format == XcmsUndefinedFormat) { + /* + * Client White Point is undefined, therefore set to the Screen + * White Point. + * Since Client White Point == Screen White Point, WhiteAdjustProc + * is not called. + */ + memcpy((char *)&clientWhitePt, + (char *)&ccc->pPerScrnInfo->screenWhitePt, + sizeof(XcmsColor)); + } else if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc, + &clientWhitePt, ScreenWhitePointOfCCC(ccc))) { + /* + * Client White Point != Screen White Point, and WhiteAdjustProc + * is not NULL, therefore, will need to call it when + * converting between DI and DD specifications. + */ + callWhiteAdjustProc = 1; + } + } + + /* + * Make copy of array of color specifications + */ + if (nColors > 1) { + pColors_tmp = (XcmsColor *) Xmalloc(nColors * sizeof(XcmsColor)); + } else { + pColors_tmp = &Color1; + } + memcpy((char *)pColors_tmp, (char *)pColors_in_out, + nColors * sizeof(XcmsColor)); + + /* + * zero out pCompressed + */ + if (pCompressed) { + bzero((char *)pCompressed, nColors * sizeof(Bool)); + } + + if (contents_flag == DD_FORMAT || contents_flag == DI_FORMAT) { + /* + * ENTIRE ARRAY IS IN ONE FORMAT. + */ + if (XCMS_DI_ID(format) && XCMS_DI_ID(targetFormat)) { + /* + * DI-to-DI only conversion + */ + retval = _XcmsDIConvertColors(ccc, pColors_tmp, + &clientWhitePt, nColors, targetFormat); + } else if (XCMS_DD_ID(format) && XCMS_DD_ID(targetFormat)) { + /* + * DD-to-DD only conversion + * Since DD->DD there will be no compressed thus we can + * pass NULL instead of pCompressed. + */ + retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors, + targetFormat, (Bool *)NULL); + } else { + /* + * Otherwise we have: + * 1. Device-Independent to Device-Dependent Conversion + * OR + * 2. Device-Dependent to Device-Independent Conversion + * + * We need to go from oldFormat -> CIEXYZ -> targetFormat + * adjusting for white points as necessary. + */ + + if (XCMS_DI_ID(format)) { + /* + * 1. Device-Independent to Device-Dependent Conversion + */ + if (callWhiteAdjustProc) { + /* + * White Point Adjustment + * Client White Point to Screen White Point + */ + retval = (*ccc->whitePtAdjProc)(ccc, &clientWhitePt, + ScreenWhitePointOfCCC(ccc), targetFormat, + pColors_tmp, nColors, pCompressed); + } else { + if (_XcmsDIConvertColors(ccc, pColors_tmp, + &clientWhitePt, nColors, XcmsCIEXYZFormat) + == XcmsFailure) { + goto Failure; + } + retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors, + targetFormat, pCompressed); + } + } else { + /* + * 2. Device-Dependent to Device-Independent Conversion + */ + if (callWhiteAdjustProc) { + /* + * White Point Adjustment + * Screen White Point to Client White Point + */ + retval = (*ccc->whitePtAdjProc)(ccc, + ScreenWhitePointOfCCC(ccc), &clientWhitePt, + targetFormat, pColors_tmp, nColors, pCompressed); + } else { + /* + * Since DD->CIEXYZ, no compression takes place therefore + * we can pass NULL instead of pCompressed. + */ + if (_XcmsDDConvertColors(ccc, pColors_tmp, nColors, + XcmsCIEXYZFormat, (Bool *)NULL) == XcmsFailure) { + goto Failure; + } + retval = _XcmsDIConvertColors(ccc, pColors_tmp, + &clientWhitePt, nColors, targetFormat); + } + } + } + } else { + /* + * ARRAY HAS MIXED FORMATS. + */ + if ((contents_flag == (DI_FORMAT | MIX_FORMAT)) && + XCMS_DI_ID(targetFormat)) { + /* + * Convert from DI to DI in batches of contiguous formats + * + * Because DI->DI, WhiteAdjustProc not called. + */ + retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt, + nColors, targetFormat, (unsigned char)DI_FORMAT); + } else if ((contents_flag == (DD_FORMAT | MIX_FORMAT)) && + XCMS_DD_ID(targetFormat)) { + /* + * Convert from DD to DD in batches of contiguous formats + * + * Because DD->DD, WhiteAdjustProc not called. + */ + retval = ConvertMixedColors(ccc, pColors_tmp, + (XcmsColor *)NULL, nColors, targetFormat, + (unsigned char)DD_FORMAT); + } else if (XCMS_DI_ID(targetFormat)) { + /* + * We need to convert from DI-to-DI and DD-to-DI, therefore + * 1. convert DD specifications to CIEXYZ, then + * 2. convert all in batches to the target DI format. + * + * Note that ConvertMixedColors will call WhiteAdjustProc + * as necessary. + */ + + /* + * Convert only DD specifications in batches of contiguous formats + * to CIEXYZ + * + * Since DD->CIEXYZ, ConvertMixedColors will apply WhiteAdjustProc + * if required. + */ + retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt, + nColors, XcmsCIEXYZFormat, (unsigned char)DD_FORMAT); + + /* + * Because at this point we may have a mix of DI formats + * (e.g., CIEXYZ, CIELuv) we must convert the specs to the + * target DI format in batches of contiguous source formats. + */ + retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt, + nColors, targetFormat, (unsigned char)DI_FORMAT); + } else { + /* + * We need to convert from DI-to-DD and DD-to-DD, therefore + * 1. convert DI specifications to CIEXYZ, then + * 2. convert all to the DD target format. + * + * This allows white point adjustment and gamut compression + * to be applied to all the color specifications in one + * swoop if those functions do in fact modify the entire + * group of color specifications. + */ + + /* + * Convert in batches to CIEXYZ + * + * If DD->CIEXYZ, ConvertMixedColors will apply WhiteAdjustProc + * if required. + */ + if ((retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt, + nColors, XcmsCIEXYZFormat, + (unsigned char)(DI_FORMAT | DD_FORMAT))) == XcmsFailure) { + goto Failure; + } + + /* + * Convert all specifications (now in CIEXYZ format) to + * the target DD format. + * Since CIEXYZ->DD, compression MAY take place therefore + * we must pass pCompressed. + * Note that WhiteAdjustProc must be used if necessary. + */ + if (callWhiteAdjustProc) { + /* + * White Point Adjustment + * Client White Point to Screen White Point + */ + retval = (*ccc->whitePtAdjProc)(ccc, + &clientWhitePt, ScreenWhitePointOfCCC(ccc), + targetFormat, pColors_tmp, nColors, pCompressed); + } else { + retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors, + targetFormat, pCompressed); + } + } + } + + if (retval != XcmsFailure) { + memcpy((char *)pColors_in_out, (char *)pColors_tmp, + nColors * sizeof(XcmsColor)); + } + if (nColors > 1) { + Xfree((char *)pColors_tmp); + } + return(retval); + +Failure: + if (nColors > 1) { + Xfree((char *)pColors_tmp); + } + return(XcmsFailure); +} + + +/* + * NAME + * XcmsRegFormatOfPrefix + * + * SYNOPSIS + */ +XcmsColorFormat +_XcmsRegFormatOfPrefix(prefix) + char *prefix; +/* + * DESCRIPTION + * Returns a color space ID associated with the specified + * X Consortium registered color space prefix. + * + * RETURNS + * The color space ID if found; + * otherwise NULL. + */ +{ + XcmsRegColorSpaceEntry *pEntry = _XcmsRegColorSpaces; + + while (pEntry->prefix != NULL) { + if (strcmp(prefix, pEntry->prefix) == 0) { + return(pEntry->id); + } + pEntry++; + } + return(XcmsUndefinedFormat); +} diff --git a/src/xcms/HVC.c b/src/xcms/HVC.c new file mode 100644 index 0000000..26bca26 --- /dev/null +++ b/src/xcms/HVC.c @@ -0,0 +1,611 @@ +/* $Xorg: HVC.c,v 1.3 2000/08/17 19:44:36 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVC.c + * + * DESCRIPTION + * This file contains routines that support the TekHVC + * color space to include conversions to and from the CIE + * XYZ space. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <X11/Xos.h> +#include <math.h> + +/* + * DEFINES + */ +#define u_BR 0.7127 /* u' Best Red */ +#define v_BR 0.4931 /* v' Best Red */ +#define EPS 0.001 +#define CHROMA_SCALE_FACTOR 7.50725 +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846264338327950 +# endif +#endif +#ifndef degrees +# define degrees(r) ((XcmsFloat)(r) * 180.0 / PI) +#endif /* degrees */ +#ifndef radians +# define radians(d) ((XcmsFloat)(d) * PI / 180.0) +#endif /* radians */ + +/************************************************************************* + * Note: The DBL_EPSILON for ANSI is 1e-5 so my checks need to take + * this into account. If your DBL_EPSILON is different then + * adjust this define. + * + * Also note that EPS is the error factor in the calculations + * This may need to be the same as XMY_DBL_EPSILON in + * some implementations. + **************************************************************************/ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif + +/* + * EXTERNS + */ + +extern char _XcmsTekHVC_prefix[]; + +/* + * FORWARD DECLARATIONS + */ + +static int TekHVC_ParseString(); +static Status XcmsTekHVC_ValidSpec(); + + +/* + * LOCAL VARIABLES + */ + + /* + * NULL terminated list of functions applied to get from TekHVC to CIEXYZ + */ +static XcmsConversionProc Fl_TekHVC_to_CIEXYZ[] = { + XcmsTekHVCToCIEuvY, + XcmsCIEuvYToCIEXYZ, + NULL +}; + + /* + * NULL terminated list of functions applied to get from CIEXYZ to TekHVC + */ +static XcmsConversionProc Fl_CIEXYZ_to_TekHVC[] = { + XcmsCIEXYZToCIEuvY, + XcmsCIEuvYToTekHVC, + NULL +}; + +/* + * GLOBALS + */ + + /* + * TekHVC Color Space + */ +XcmsColorSpace XcmsTekHVCColorSpace = + { + _XcmsTekHVC_prefix, /* prefix */ + XcmsTekHVCFormat, /* id */ + TekHVC_ParseString, /* parseString */ + Fl_TekHVC_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_TekHVC, /* from_CIEXYZ */ + 1 + }; + + + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * TekHVC_ParseString + * + * SYNOPSIS + */ +static int +TekHVC_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsTekHVCFormat. + * The assumed TekHVC string syntax is: + * TekHVC:<H>/<V>/<C> + * Where H, V, and C are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * XcmsFailure if invalid; + * XcmsSuccess if valid. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsTekHVC_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.TekHVC.H, + &pColor->spec.TekHVC.V, + &pColor->spec.TekHVC.C) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsTekHVCFormat; + pColor->pixel = 0; + return(XcmsTekHVC_ValidSpec(pColor)); +} + + +/* + * NAME + * ThetaOffset -- compute thetaOffset + * + * SYNOPSIS + */ +static int +ThetaOffset(pWhitePt, pThetaOffset) + XcmsColor *pWhitePt; + XcmsFloat *pThetaOffset; +/* + * DESCRIPTION + * This routine computes the theta offset of a given + * white point, i.e. XcmsColor. It is used in both this + * conversion and the printer conversions. + * + * RETURNS + * 0 if failed. + * 1 if succeeded with no modifications. + * + * ASSUMPTIONS + * Assumes: + * pWhitePt != NULL + * pWhitePt->format == XcmsCIEuvYFormat + * + */ +{ + double div, slopeuv; + + if (pWhitePt == NULL || pWhitePt->format != XcmsCIEuvYFormat) { + return(0); + } + + if ((div = u_BR - pWhitePt->spec.CIEuvY.u_prime) == 0.0) { + return(0); + } + slopeuv = (v_BR - pWhitePt->spec.CIEuvY.v_prime) / div; + *pThetaOffset = degrees(XCMS_ATAN(slopeuv)); + return(1); +} + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVC_ValidSpec() + * + * SYNOPSIS + */ +static int +XcmsTekHVC_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if values in the color specification are valid. + * Also brings hue into the range 0.0 <= Hue < 360.0 + * + * RETURNS + * 0 if not valid. + * 1 if valid. + * + */ +{ + if (pColor->format != XcmsTekHVCFormat) { + return(XcmsFailure); + } + if (pColor->spec.TekHVC.V < (0.0 - XMY_DBL_EPSILON) + || pColor->spec.TekHVC.V > (100.0 + XMY_DBL_EPSILON) + || (pColor->spec.TekHVC.C < 0.0 - XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + + if (pColor->spec.TekHVC.V < 0.0) { + pColor->spec.TekHVC.V = 0.0 + XMY_DBL_EPSILON; + } else if (pColor->spec.TekHVC.V > 100.0) { + pColor->spec.TekHVC.V = 100.0 - XMY_DBL_EPSILON; + } + + if (pColor->spec.TekHVC.C < 0.0) { + pColor->spec.TekHVC.C = 0.0 - XMY_DBL_EPSILON; + } + + while (pColor->spec.TekHVC.H < 0.0) { + pColor->spec.TekHVC.H += 360.0; + } + while (pColor->spec.TekHVC.H >= 360.0) { + pColor->spec.TekHVC.H -= 360.0; + } + return(XcmsSuccess); +} + +/* + * NAME + * XcmsTekHVCToCIEuvY - convert TekHVC to CIEuvY + * + * SYNOPSIS + */ +Status +XcmsTekHVCToCIEuvY(ccc, pHVC_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pHVC_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Transforms an array of TekHVC color specifications, given + * their associated white point, to CIECIEuvY.color + * specifications. + * + * RETURNS + * XcmsFailure if failed, XcmsSuccess otherwise. + * + */ +{ + XcmsFloat thetaOffset; + XcmsColor *pColor = pColors_in_out; + XcmsColor whitePt; + XcmsCIEuvY uvY_return; + XcmsFloat tempHue, u, v; + XcmsFloat tmpVal; + register int i; + + /* + * Check arguments + */ + if (pHVC_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEuvY form + */ + if (pHVC_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pHVC_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, 1, + XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + pHVC_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (pHVC_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + + /* Get the thetaOffset */ + if (!ThetaOffset(pHVC_WhitePt, &thetaOffset)) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is TekHVC and is valid */ + if (!XcmsTekHVC_ValidSpec(pColor)) { + return(XcmsFailure); + } + + if (pColor->spec.TekHVC.V == 0.0 || pColor->spec.TekHVC.V == 100.0) { + if (pColor->spec.TekHVC.V == 100.0) { + uvY_return.Y = 1.0; + } else { /* pColor->spec.TekHVC.V == 0.0 */ + uvY_return.Y = 0.0; + } + uvY_return.u_prime = pHVC_WhitePt->spec.CIEuvY.u_prime; + uvY_return.v_prime = pHVC_WhitePt->spec.CIEuvY.v_prime; + } else { + + /* Find the hue based on the white point offset */ + tempHue = pColor->spec.TekHVC.H + thetaOffset; + + while (tempHue < 0.0) { + tempHue += 360.0; + } + while (tempHue >= 360.0) { + tempHue -= 360.0; + } + + tempHue = radians(tempHue); + + /* Calculate u'v' for the obtained hue */ + u = (XcmsFloat) ((XCMS_COS(tempHue) * pColor->spec.TekHVC.C) / + (pColor->spec.TekHVC.V * (double)CHROMA_SCALE_FACTOR)); + v = (XcmsFloat) ((XCMS_SIN(tempHue) * pColor->spec.TekHVC.C) / + (pColor->spec.TekHVC.V * (double)CHROMA_SCALE_FACTOR)); + + /* Based on the white point get the offset from best red */ + uvY_return.u_prime = u + pHVC_WhitePt->spec.CIEuvY.u_prime; + uvY_return.v_prime = v + pHVC_WhitePt->spec.CIEuvY.v_prime; + + /* Calculate the Y value based on the L* = V. */ + if (pColor->spec.TekHVC.V < 7.99953624) { + uvY_return.Y = pColor->spec.TekHVC.V / 903.29; + } else { + tmpVal = (pColor->spec.TekHVC.V + 16.0) / 116.0; + uvY_return.Y = tmpVal * tmpVal * tmpVal; /* tmpVal ** 3 */ + } + } + + /* Copy result to pColor */ + memcpy((char *)&pColor->spec, (char *)&uvY_return, sizeof(XcmsCIEuvY)); + + /* Identify that the format is now CIEuvY */ + pColor->format = XcmsCIEuvYFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEuvYToTekHVC - convert CIEuvY to TekHVC + * + * SYNOPSIS + */ +Status +XcmsCIEuvYToTekHVC(ccc, pHVC_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pHVC_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Transforms an array of CIECIEuvY.color specifications, given + * their assiciated white point, to TekHVC specifications. + * + * RETURNS + * XcmsFailure if failed, XcmsSuccess otherwise. + * + */ +{ + XcmsFloat theta, L2, u, v, nThetaLow, nThetaHigh; + XcmsFloat thetaOffset; + XcmsColor *pColor = pColors_in_out; + XcmsColor whitePt; + XcmsTekHVC HVC_return; + register int i; + + /* + * Check arguments + */ + if (pHVC_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEuvY form + */ + if (pHVC_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pHVC_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, 1, + XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + pHVC_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (pHVC_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + if (!ThetaOffset(pHVC_WhitePt, &thetaOffset)) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + if (!_XcmsCIEuvY_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* Use the white point offset to determine HVC */ + u = pColor->spec.CIEuvY.u_prime - pHVC_WhitePt->spec.CIEuvY.u_prime; + v = pColor->spec.CIEuvY.v_prime - pHVC_WhitePt->spec.CIEuvY.v_prime; + + /* Calculate the offset */ + if (u == 0.0) { + theta = 0.0; + } else { + theta = v / u; + theta = (XcmsFloat) XCMS_ATAN((double)theta); + theta = degrees(theta); + } + + nThetaLow = 0.0; + nThetaHigh = 360.0; + if (u > 0.0 && v > 0.0) { + nThetaLow = 0.0; + nThetaHigh = 90.0; + } else if (u < 0.0 && v > 0.0) { + nThetaLow = 90.0; + nThetaHigh = 180.0; + } else if (u < 0.0 && v < 0.0) { + nThetaLow = 180.0; + nThetaHigh = 270.0; + } else if (u > 0.0 && v < 0.0) { + nThetaLow = 270.0; + nThetaHigh = 360.0; + } + while (theta < nThetaLow) { + theta += 90.0; + } + while (theta >= nThetaHigh) { + theta -= 90.0; + } + + /* calculate the L value from the given Y */ + L2 = (pColor->spec.CIEuvY.Y < 0.008856) + ? + (pColor->spec.CIEuvY.Y * 903.29) + : + ((XcmsFloat)(XCMS_CUBEROOT(pColor->spec.CIEuvY.Y) * 116.0) - 16.0); + HVC_return.C = L2 * CHROMA_SCALE_FACTOR * XCMS_SQRT((double) ((u * u) + (v * v))); + if (HVC_return.C < 0.0) { + theta = 0.0; + } + HVC_return.V = L2; + HVC_return.H = theta - thetaOffset; + + /* + * If this is within the error margin let some other routine later + * in the chain worry about the slop in the calculations. + */ + while (HVC_return.H < -EPS) { + HVC_return.H += 360.0; + } + while (HVC_return.H >= 360.0 + EPS) { + HVC_return.H -= 360.0; + } + + /* Copy result to pColor */ + memcpy((char *)&pColor->spec, (char *)&HVC_return, sizeof(XcmsTekHVC)); + + /* Identify that the format is now CIEuvY */ + pColor->format = XcmsTekHVCFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * _XcmsTekHVC_CheckModify + * + * SYNOPSIS + */ +int +_XcmsTekHVC_CheckModify(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if values in the color specification are valid. + * If they are not it modifies the values. + * Also brings hue into the range 0.0 <= Hue < 360.0 + * + * RETURNS + * 0 if not valid. + * 1 if valid. + * + */ +{ + int n; + + /* For now only use the TekHVC numbers as inputs */ + if (pColor->format != XcmsTekHVCFormat) { + return(0); + } + + if (pColor->spec.TekHVC.V < 0.0) { + pColor->spec.TekHVC.V = 0.0 + XMY_DBL_EPSILON; + } else if (pColor->spec.TekHVC.V > 100.0) { + pColor->spec.TekHVC.V = 100.0 - XMY_DBL_EPSILON; + } + + if (pColor->spec.TekHVC.C < 0.0) { + pColor->spec.TekHVC.C = 0.0 - XMY_DBL_EPSILON; + } + + if (pColor->spec.TekHVC.H < 0.0) { + n = -pColor->spec.TekHVC.H / 360.0; + pColor->spec.TekHVC.H += (n + 1) * 360.0; + if (pColor->spec.TekHVC.H >= 360.0) + pColor->spec.TekHVC.H -= 360.0; + } else if (pColor->spec.TekHVC.H >= 360.0) { + n = pColor->spec.TekHVC.H / 360.0; + pColor->spec.TekHVC.H -= n * 360.0; + } + return(1); +} diff --git a/src/xcms/HVCGcC.c b/src/xcms/HVCGcC.c new file mode 100644 index 0000000..26a3f12 --- /dev/null +++ b/src/xcms/HVCGcC.c @@ -0,0 +1,153 @@ +/* $Xorg: HVCGcC.c,v 1.3 2000/08/17 19:44:36 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCGcC.c + * + * DESCRIPTION + * Source for XcmsTekHVCClipC() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern XcmsColorSpace XcmsTekHVCColorSpace; +extern XcmsFunctionSet XcmsLinearRGBFunctionSet; + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCClipC - Reduce the chroma for a hue and value + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsTekHVCClipC (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Reduce the Chroma for a specific hue and value to + * to bring the given color into the gamut of the + * specified device. As required of gamut compression + * functions in Xcms, this routine returns pColor_in_out + * in XcmsCIEXYZFormat on successful completion. + * + * Since this routine works with the value within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsColor *pColor; + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor && + FunctionSetOfCCC(ccc) != (XPointer) &XcmsLinearRGBFunctionSet) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt, + 1, XcmsTekHVCFormat); + pColor->spec.TekHVC.H = pColor->spec.TekHVC.C = 0.0; + _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt, + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } else { + if (pColor->format != XcmsTekHVCFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsTekHVCQueryMaxC(ccc, + pColor->spec.TekHVC.H, + pColor->spec.TekHVC.V, + pColor) + == XcmsFailure) { + return(XcmsFailure); + } + retval = _XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/HVCGcV.c b/src/xcms/HVCGcV.c new file mode 100644 index 0000000..7b06212 --- /dev/null +++ b/src/xcms/HVCGcV.c @@ -0,0 +1,206 @@ +/* $Xorg: HVCGcV.c,v 1.3 2000/08/17 19:44:36 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCGcV.c + * + * DESCRIPTION + * Source for XcmsTekHVCClipV() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern Status _XcmsTekHVC_CheckModify(); +extern XcmsColorSpace XcmsTekHVCColorSpace; +extern XcmsFunctionSet XcmsLinearRGBFunctionSet; + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCClipV - Return the closest value + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsTekHVCClipV (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Return the closest value for a specific hue and chroma. + * This routine takes any color as input and outputs + * a CIE XYZ color. + * + * Since this routine works with the value within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsColor *pColor; + XcmsColor hvc_max; + XcmsCCCRec myCCC; + Status retval; + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor && + FunctionSetOfCCC(ccc) != (XPointer) &XcmsLinearRGBFunctionSet) { + /* + * GRAY ! + */ + return(XcmsFailure); + } else { + /* Convert from CIEXYZ to TekHVC format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + /* check to make sure we have a valid TekHVC number */ + if (!_XcmsTekHVC_CheckModify (pColor)) { + return (XcmsFailure); + } + + /* Step 1: compute the maximum value and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&hvc_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsTekHVCQueryMaxVCRGB (&myCCC, hvc_max.spec.TekHVC.H, &hvc_max, + (XcmsRGBi *)NULL) == XcmsFailure) { + return (XcmsFailure); + } + + /* Now check and return the appropriate value */ + if (pColor->spec.TekHVC.C == hvc_max.spec.TekHVC.C) { + /* When the chroma input is equal to the maximum chroma */ + /* merely return the value for that chroma. */ + pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V; + if (!_XcmsTekHVC_CheckModify (pColor)) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + } else if (pColor->spec.TekHVC.C > hvc_max.spec.TekHVC.C) { + /* When the chroma input is greater than the maximum chroma */ + /* merely return the value and chroma for the given hue. */ + pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C; + pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V; + return (XcmsFailure); + } else if (pColor->spec.TekHVC.V < hvc_max.spec.TekHVC.V) { + /* When the value input is less than the maximum value point */ + /* compute the intersection of the line from 0,0 to max_V, max_C */ + /* using the chroma input. */ + pColor->spec.TekHVC.V = pColor->spec.TekHVC.C * + hvc_max.spec.TekHVC.V / hvc_max.spec.TekHVC.C; + if (pColor->spec.TekHVC.V >= hvc_max.spec.TekHVC.V) { + pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C; + pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V; + } + if (!_XcmsTekHVC_CheckModify (pColor)) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + } else { + /* When the value input is greater than the maximum value point */ + /* use HvcMaxValue to find the maximum value for the given chroma. */ + if (pColor->format != XcmsTekHVCFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsTekHVCQueryMaxV(&myCCC, + pColor->spec.TekHVC.H, + pColor->spec.TekHVC.C, + pColor) + == XcmsFailure) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + } + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/HVCGcVC.c b/src/xcms/HVCGcVC.c new file mode 100644 index 0000000..00d09b2 --- /dev/null +++ b/src/xcms/HVCGcVC.c @@ -0,0 +1,267 @@ +/* $Xorg: HVCGcVC.c,v 1.3 2000/08/17 19:44:36 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCGcVC.c + * + * DESCRIPTION + * Source for XcmsTekHVCClipVC() gamut + * compression function. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * INTERNALS + * Internal defines that need NOT be exported to any package or + * program using this package. + */ +#define MAXBISECTCOUNT 100 + +/* + * EXTERNS + */ +extern int _XcmsTekHVC_CheckModify(); +extern Status _XcmsTekHVCQueryMaxVCRGB(); +extern XcmsColorSpace XcmsTekHVCColorSpace; +extern XcmsFunctionSet XcmsLinearRGBFunctionSet; + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCClipVC - Return the closest value and chroma + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsTekHVCClipVC (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * This routine will find the closest value and chroma + * for a specific hue. The color input is converted to + * HVC format and returned as CIE XYZ format. + * + * Since this routine works with the value within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsCCCRec myCCC; + XcmsColor *pColor; + XcmsColor hvc_max; + XcmsRGBi rgb_max; + int nCount, nMaxCount, nI, nILast; + XcmsFloat Chroma, Value, bestChroma, bestValue, nT, saveDist, tmpDist; + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* inherit screen white pt */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression func */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor && + FunctionSetOfCCC(ccc) != (XPointer) &XcmsLinearRGBFunctionSet) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt, + 1, XcmsTekHVCFormat); + pColor->spec.TekHVC.H = pColor->spec.TekHVC.C = 0.0; + _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt, + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } else { + /* Convert from CIEXYZ to TekHVC format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + if (!_XcmsTekHVC_CheckModify(pColor)) { + return (XcmsFailure); + } + + /* Step 1: compute the maximum value and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&hvc_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsTekHVCQueryMaxVCRGB (&myCCC, hvc_max.spec.TekHVC.H, &hvc_max, + &rgb_max) == XcmsFailure) { + return (XcmsFailure); + } + + /* Now check and return the appropriate value */ + if (pColor->spec.TekHVC.V == hvc_max.spec.TekHVC.V) { + /* When the value input is equal to the maximum value */ + /* merely return the chroma for that value. */ + pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C; + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + } + + if (pColor->spec.TekHVC.V < hvc_max.spec.TekHVC.V) { + /* return the intersection of the perpindicular line through */ + /* the value and chroma given and the line from 0,0 and hvc_max. */ + Chroma = pColor->spec.TekHVC.C; + Value = pColor->spec.TekHVC.V; + pColor->spec.TekHVC.C = + (Value + (hvc_max.spec.TekHVC.C / hvc_max.spec.TekHVC.V * Chroma)) / + ((hvc_max.spec.TekHVC.V / hvc_max.spec.TekHVC.C) + + (hvc_max.spec.TekHVC.C / hvc_max.spec.TekHVC.V)); + if (pColor->spec.TekHVC.C >= hvc_max.spec.TekHVC.C) { + pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C; + pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V; + } else { + pColor->spec.TekHVC.V = pColor->spec.TekHVC.C * + hvc_max.spec.TekHVC.V / hvc_max.spec.TekHVC.C; + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return (retval); + } + + /* return the closest point on the upper part of the hue leaf. */ + /* must do a bisection here to compute the delta e. */ + nMaxCount = MAXBISECTCOUNT; + nI = nMaxCount / 2; + bestValue = Value = pColor->spec.TekHVC.V; + bestChroma = Chroma = pColor->spec.TekHVC.C; + saveDist = (XcmsFloat) XCMS_SQRT ((double) (((Chroma - hvc_max.spec.TekHVC.C) * + (Chroma - hvc_max.spec.TekHVC.C)) + + ((Value - hvc_max.spec.TekHVC.V) * + (Value - hvc_max.spec.TekHVC.V)))); + for (nCount = 0; nCount < nMaxCount; nCount++) { + nT = (XcmsFloat) nI / (XcmsFloat) nMaxCount; + pColor->spec.RGBi.red = rgb_max.red * (1.0 - nT) + nT; + pColor->spec.RGBi.green = rgb_max.green * (1.0 - nT) + nT; + pColor->spec.RGBi.blue = rgb_max.blue * (1.0 - nT) + nT; + pColor->format = XcmsRGBiFormat; + + /* Convert from RGBi to HVC */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, + (Bool *) NULL) + == XcmsFailure) { + return (XcmsFailure); + } + if (!_XcmsTekHVC_CheckModify(pColor)) { + return (XcmsFailure); + } + tmpDist = (XcmsFloat) XCMS_SQRT ((double) + (((Chroma - pColor->spec.TekHVC.C) * + (Chroma - pColor->spec.TekHVC.C)) + + ((Value - pColor->spec.TekHVC.V) * + (Value - pColor->spec.TekHVC.V)))); + nILast = nI; + if (tmpDist > saveDist) { + nI /= 2; + } else { + nI = (nMaxCount + nI) / 2; + saveDist = tmpDist; + bestValue = pColor->spec.TekHVC.V; + bestChroma = pColor->spec.TekHVC.C; + } + if (nI == nILast || nI == 0) { + break; + } + + } + + if (bestChroma >= hvc_max.spec.TekHVC.C) { + pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C; + pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V; + } else { + pColor->spec.TekHVC.C = bestChroma; + pColor->spec.TekHVC.V = bestValue; + } + if (!_XcmsTekHVC_CheckModify(pColor)) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/HVCMnV.c b/src/xcms/HVCMnV.c new file mode 100644 index 0000000..f66e0e1 --- /dev/null +++ b/src/xcms/HVCMnV.c @@ -0,0 +1,167 @@ +/* $Xorg: HVCMnV.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCMnV.c + * + * DESCRIPTION + * Source for XcmsTekHVCQueryMinV gamut boundary querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define EPS 0.001 + +/* + * EXTERNS + */ +extern Status _XcmsTekHVCQueryMaxVCRGB(); +extern Status _XcmsTekHVC_CheckModify(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCQueryMinV - Compute minimum value for hue and chroma + * + * SYNOPSIS + */ +Status +XcmsTekHVCQueryMinV (ccc, hue, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue; + XcmsFloat chroma; + XcmsColor *pColor_return; + +/* + * DESCRIPTION + * Return the minimum value for a specific hue, and the + * corresponding chroma. The input color specification + * may be in any format, however output is in XcmsTekHVCFormat. + * + * Since this routine works with the value within + * pColor_return intermediate results may be returned + * even though it may be invalid. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor tmp; + XcmsColor max_vc; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* inherit screen white pt */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut comp func */ + + tmp.spec.TekHVC.H = hue; + tmp.spec.TekHVC.V = 100.0; + tmp.spec.TekHVC.C = chroma; + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsTekHVCFormat; + + + /* Check for a valid HVC */ + if (!_XcmsTekHVC_CheckModify (&tmp)) { + return(XcmsFailure); + } + + /* Step 1: compute the maximum value and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&max_vc, (char *)&tmp, sizeof(XcmsColor)); + if (_XcmsTekHVCQueryMaxVCRGB (&myCCC, max_vc.spec.TekHVC.H, &max_vc, + (XcmsRGBi *)NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Step 2: find the intersection with the maximum hvc and chroma line. */ + if (tmp.spec.TekHVC.C > max_vc.spec.TekHVC.C + EPS) { + /* If the chroma is to large then return maximum hvc. */ + tmp.spec.TekHVC.C = max_vc.spec.TekHVC.C; + tmp.spec.TekHVC.V = max_vc.spec.TekHVC.V; + } else { + tmp.spec.TekHVC.V = tmp.spec.TekHVC.C * + max_vc.spec.TekHVC.V / max_vc.spec.TekHVC.C; + if (tmp.spec.TekHVC.V > max_vc.spec.TekHVC.V) { + tmp.spec.TekHVC.V = max_vc.spec.TekHVC.V; + } else if (tmp.spec.TekHVC.V < 0.0) { + tmp.spec.TekHVC.V = tmp.spec.TekHVC.C = 0.0; + } + } + if (_XcmsTekHVC_CheckModify (&tmp)) { + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } else { + return(XcmsFailure); + } +} diff --git a/src/xcms/HVCMxC.c b/src/xcms/HVCMxC.c new file mode 100644 index 0000000..e7e316f --- /dev/null +++ b/src/xcms/HVCMxC.c @@ -0,0 +1,247 @@ +/* $Xorg: HVCMxC.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCMxC.c + * + * DESCRIPTION + * Source for the XcmsTekHVCQueryMaxC() gamut boudary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS 0.001 + +/* + * EXTERNS + */ +extern Status _XcmsTekHVCQueryMaxVCRGB(); +extern int _XcmsTekHVC_CheckModify(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCQueryMaxC - Compute the maximum chroma for a hue and value + * + * SYNOPSIS + */ +Status +XcmsTekHVCQueryMaxC(ccc, hue, value, pColor_return) + XcmsCCC ccc; + XcmsFloat hue; + XcmsFloat value; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum chroma for a specific hue and value. + * The returned format is in XcmsTekHVCFormat. + * + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor tmp; + XcmsColor max_vc; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + XcmsFloat nValue, savedValue, lastValue, lastChroma, prevValue; + XcmsFloat maxDist, nT, rFactor; + XcmsFloat ftmp1, ftmp2; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; /* inherit screen white Pt */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut comp func */ + + tmp.spec.TekHVC.H = hue; + tmp.spec.TekHVC.V = value; + tmp.spec.TekHVC.C = 100.0; + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsTekHVCFormat; + + /* check to make sure we have a valid TekHVC number */ + if (!_XcmsTekHVC_CheckModify(&tmp)) { + return(XcmsFailure); + } + + /* Step 1: compute the maximum value and chroma for this hue. */ + memcpy((char *)&max_vc, (char *)&tmp, sizeof(XcmsColor)); + if (_XcmsTekHVCQueryMaxVCRGB(&myCCC, hue, &max_vc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + /* Step 2: If the value is less than the value for the maximum */ + /* value, chroma point then the chroma is on the line */ + /* from max_vc to 0,0. */ + if (value <= max_vc.spec.TekHVC.V) { + tmp.spec.TekHVC.C = value + * max_vc.spec.TekHVC.C / max_vc.spec.TekHVC.V; + if (_XcmsTekHVC_CheckModify (&tmp)) { + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); + } else { + return(XcmsFailure); + } + } else { + /* must do a bisection here to compute the maximum chroma */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nValue = savedValue = value; + lastValue = -1.0; + nMaxCount = MAXBISECTCOUNT; + maxDist = 100.0 - max_vc.spec.TekHVC.V; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevValue = lastValue; + lastValue = tmp.spec.TekHVC.V; + lastChroma = tmp.spec.TekHVC.C; + nT = (nValue - max_vc.spec.TekHVC.V) / maxDist * rFactor; + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to HVC */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + if (tmp.spec.TekHVC.V <= savedValue + EPS && + tmp.spec.TekHVC.V >= savedValue - EPS) { + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + if (_XcmsTekHVC_CheckModify (&tmp)) { + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); + } else { + return(XcmsFailure); + } + } + nValue += savedValue - tmp.spec.TekHVC.V; + if (nValue < max_vc.spec.TekHVC.V) { + nValue = max_vc.spec.TekHVC.V; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nValue > 100.0) { + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + /* avoid using fabs */ + ftmp1 = lastValue - savedValue; + if (ftmp1 < 0.0) + ftmp1 = -ftmp1; + ftmp2 = tmp.spec.TekHVC.V - savedValue; + if (ftmp2 < 0.0) + ftmp2 = -ftmp2; + if (ftmp1 < ftmp2) { + tmp.spec.TekHVC.V = lastValue; + tmp.spec.TekHVC.C = lastChroma; + } + if (_XcmsTekHVC_CheckModify (&tmp)) { + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); + } else { + return(XcmsFailure); + } + } else if (tmp.spec.TekHVC.V <= prevValue + EPS && + tmp.spec.TekHVC.V >= prevValue - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + if (nCount >= nMaxCount) { + /* avoid using fabs */ + ftmp1 = lastValue - savedValue; + if (ftmp1 < 0.0) + ftmp1 = -ftmp1; + ftmp2 = tmp.spec.TekHVC.V - savedValue; + if (ftmp2 < 0.0) + ftmp2 = -ftmp2; + if (ftmp1 < ftmp2) { + tmp.spec.TekHVC.V = lastValue; + tmp.spec.TekHVC.C = lastChroma; + } + } + } + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/HVCMxV.c b/src/xcms/HVCMxV.c new file mode 100644 index 0000000..b1e7009 --- /dev/null +++ b/src/xcms/HVCMxV.c @@ -0,0 +1,250 @@ +/* $Xorg: HVCMxV.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCMxV.c + * + * DESCRIPTION + * Source for the XcmsTekHVCQueryMaxV() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS 0.001 + +/* + * EXTERNS + */ +extern Status _XcmsTekHVCQueryMaxVCRGB(); +extern int _XcmsTekHVC_CheckModify(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCQueryMaxV - Compute maximum value for a hue and chroma + * + * SYNOPSIS + */ +Status +XcmsTekHVCQueryMaxV(ccc, hue, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue; + XcmsFloat chroma; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum value for a specified hue and chroma. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor tmp; + XcmsColor max_vc; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + XcmsFloat nT, nChroma, savedChroma, lastValue, lastChroma, prevChroma; + XcmsFloat rFactor; + XcmsFloat ftmp1, ftmp2; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + tmp.spec.TekHVC.H = hue; + tmp.spec.TekHVC.V = 0.0; + tmp.spec.TekHVC.C = chroma; + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsTekHVCFormat; + + if (!_XcmsTekHVC_CheckModify (&tmp)) { + return(XcmsFailure); + } + + /* Step 1: compute the maximum value and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&max_vc, (char *)&tmp, sizeof(XcmsColor)); + hue = max_vc.spec.TekHVC.H; + if (_XcmsTekHVCQueryMaxVCRGB(&myCCC, max_vc.spec.TekHVC.H, &max_vc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + if (max_vc.spec.TekHVC.C < tmp.spec.TekHVC.C) { + /* + * If the chroma is greater than the chroma for the + * maximum value/chroma point then the value is the + * the value for the maximum value, chroma point. + * This is an error but it I return the best approximation I can. + * Thus the inconsistency. + */ + tmp.spec.TekHVC.C = max_vc.spec.TekHVC.C; + tmp.spec.TekHVC.V = max_vc.spec.TekHVC.V; + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } else if (max_vc.spec.TekHVC.C == tmp.spec.TekHVC.C) { + /* + * If the chroma is equal to the chroma for the + * maximum value/chroma point then the value is the + * the value for the maximum value, chroma point. + */ + tmp.spec.TekHVC.V = max_vc.spec.TekHVC.V; + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } else { + /* must do a bisection here to compute the maximum value */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nChroma = savedChroma = tmp.spec.TekHVC.C; + tmp.spec.TekHVC.C = max_vc.spec.TekHVC.C; + tmp.spec.TekHVC.V = max_vc.spec.TekHVC.V; + lastChroma = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevChroma = lastChroma; + lastValue = tmp.spec.TekHVC.V; + lastChroma = tmp.spec.TekHVC.C; + nT = (1.0 - (nChroma / max_vc.spec.TekHVC.C)) * rFactor; + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to HVC */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + if (tmp.spec.TekHVC.C <= savedChroma + EPS && + tmp.spec.TekHVC.C >= savedChroma - EPS) { + tmp.spec.TekHVC.H = hue; /* use the saved hue */ + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } + nChroma += savedChroma - tmp.spec.TekHVC.C; + if (nChroma > max_vc.spec.TekHVC.C) { + nChroma = max_vc.spec.TekHVC.C; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nChroma < 0.0) { + /* avoid using fabs */ + ftmp1 = lastChroma - savedChroma; + if (ftmp1 < 0.0) + ftmp1 = -ftmp1; + ftmp2 = tmp.spec.TekHVC.C - savedChroma; + if (ftmp2 < 0.0) + ftmp2 = -ftmp2; + if (ftmp1 < ftmp2) { + tmp.spec.TekHVC.V = lastValue; + tmp.spec.TekHVC.C = lastChroma; + } + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + if (!_XcmsTekHVC_CheckModify(&tmp)) { + return(XcmsFailure); + } + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } else if (tmp.spec.TekHVC.C <= prevChroma + EPS && + tmp.spec.TekHVC.C >= prevChroma - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + if (nCount >= nMaxCount) { + /* avoid using fabs */ + ftmp1 = lastChroma - savedChroma; + if (ftmp1 < 0.0) + ftmp1 = -ftmp1; + ftmp2 = tmp.spec.TekHVC.C - savedChroma; + if (ftmp2 < 0.0) + ftmp2 = -ftmp2; + if (ftmp1 < ftmp2) { + tmp.spec.TekHVC.V = lastValue; + tmp.spec.TekHVC.C = lastChroma; + } + } + } + + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/HVCMxVC.c b/src/xcms/HVCMxVC.c new file mode 100644 index 0000000..7c8ec7d --- /dev/null +++ b/src/xcms/HVCMxVC.c @@ -0,0 +1,244 @@ +/* $Xorg: HVCMxVC.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCMxVC.c + * + * DESCRIPTION + * Source for the XcmsTekHVCQueryMaxVC() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) +#define START_V 40.0 +#define START_C 120.0 + +/* + * EXTERNS + */ +extern Status _XcmsTekHVC_CheckModify(); +extern Status _XcmsConvertColorsWithWhitePt(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + +/* + * FORWARD DECLARATIONS + */ +Status _XcmsTekHVCQueryMaxVCRGB(); + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsTekHVCQueryMaxVCRGB - Compute maximum value/chroma. + * + * SYNOPSIS + */ +Status +_XcmsTekHVCQueryMaxVCRGB(ccc, hue, pColor_return, pRGB_return) + XcmsCCC ccc; + XcmsFloat hue; + XcmsColor *pColor_return; + XcmsRGBi *pRGB_return; + +/* + * DESCRIPTION + * Return the maximum chroma for a specified hue, and the + * corresponding value. This is computed by a binary search of + * all possible chromas. An assumption is made that there are + * no local maxima. Use the unrounded Max Chroma because + * the difference check can be small. + * + * NOTE: No local CCC is used because this is a private + * routine and all routines that call it are expected + * to behave properly, i.e. send a local CCC with + * no white adjust function and no gamut compression + * function. + * + * This routine only accepts hue as input and outputs + * HVC's and RGBi's. + * + * RETURNS + * XcmsFailure - Failure + * XCMS_SUCCUSS - Succeeded + * + */ +{ + XcmsFloat nSmall, nLarge; + XcmsColor tmp; + + tmp.format = XcmsTekHVCFormat; + tmp.spec.TekHVC.H = hue; + /* Use some unreachable color on the given hue */ + tmp.spec.TekHVC.V = START_V; + tmp.spec.TekHVC.C = START_C; + + + /* + * Convert from HVC to RGB + * + * Note that the CIEXYZ to RGBi conversion routine must stuff the + * out of bounds RGBi values in tmp when the ccc->gamutCompProc + * is NULL. + */ + if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsRGBiFormat, (Bool *) NULL) + == XcmsFailure) && tmp.format != XcmsRGBiFormat) { + return (XcmsFailure); + } + + /* Now pick the smallest RGB */ + nSmall = MIN3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Make the smallest RGB equal to zero */ + tmp.spec.RGBi.red -= nSmall; + tmp.spec.RGBi.green -= nSmall; + tmp.spec.RGBi.blue -= nSmall; + + /* Now pick the largest RGB */ + nLarge = MAX3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Scale the RGB values based on the largest one */ + tmp.spec.RGBi.red /= nLarge; + tmp.spec.RGBi.green /= nLarge; + tmp.spec.RGBi.blue /= nLarge; + tmp.format = XcmsRGBiFormat; + + /* If the calling routine wants RGB value give them the ones used. */ + if (pRGB_return) { + pRGB_return->red = tmp.spec.RGBi.red; + pRGB_return->green = tmp.spec.RGBi.green; + pRGB_return->blue = tmp.spec.RGBi.blue; + } + + /* Convert from RGBi to HVC */ + if (_XcmsConvertColorsWithWhitePt(ccc, &tmp, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, (Bool *) NULL) + == XcmsFailure) { + return (XcmsFailure); + } + + /* make sure to return the input hue */ + tmp.spec.TekHVC.H = hue; + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return (XcmsSuccess); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCQueryMaxVC - Compute maximum value and chroma. + * + * SYNOPSIS + */ +Status +XcmsTekHVCQueryMaxVC (ccc, hue, pColor_return) + XcmsCCC ccc; + XcmsFloat hue; + XcmsColor *pColor_return; + +/* + * DESCRIPTION + * Return the maximum chroma for the specified hue, and the + * corresponding value. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc)NULL; + + while (hue < 0.0) { + hue += 360.0; + } + while (hue >= 360.0) { + hue -= 360.0; + } + + return(_XcmsTekHVCQueryMaxVCRGB (&myCCC, hue, pColor_return, + (XcmsRGBi *)NULL)); +} diff --git a/src/xcms/HVCMxVs.c b/src/xcms/HVCMxVs.c new file mode 100644 index 0000000..33f84b6 --- /dev/null +++ b/src/xcms/HVCMxVs.c @@ -0,0 +1,166 @@ +/* $Xorg: HVCMxVs.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * TekHVCMxVs.c + * + * DESCRIPTION + * Source for the XcmsTekHVCQueryMaxVSamples() gamut boundary + * querying routine. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern Status _XcmsTekHVCQueryMaxVCRGB(); +extern Status _XcmsTekHVC_CheckModify(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCQueryMaxVSamples - Compute a set of value/chroma + * pairs. + * + * SYNOPSIS + */ +Status +XcmsTekHVCQueryMaxVSamples(ccc, hue, pColor_in_out, nSamples) + XcmsCCC ccc; + XcmsFloat hue; + XcmsColor *pColor_in_out; + unsigned int nSamples; + +/* + * DESCRIPTION + * Return a set of values and chromas for the input Hue. + * This routine will take any color as input. + * It returns TekHVC colors. + * + * Since this routine works with the value within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor *pHVC; + XcmsRGBi rgb_saved; + unsigned short nI; + XcmsFloat nT; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_in_out == NULL || nSamples == 0) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + /* Step 1: compute the maximum value and chroma for this hue. */ + + + /* save the Hue for use later. */ + while (hue < 0.0) { + hue += 360.0; + } + while (hue > 360.0) { + hue -= 360.0; + } + pColor_in_out->spec.TekHVC.H = hue; + pColor_in_out->format = XcmsTekHVCFormat; + + /* Get the maximum value and chroma point for this hue */ + if (_XcmsTekHVCQueryMaxVCRGB(&myCCC, pColor_in_out->spec.TekHVC.H, + pColor_in_out, (XcmsRGBi *)&rgb_saved) == XcmsFailure) { + return (XcmsFailure); + } + + /* Step 2: Convert each of the RGBi's to HVC's */ + pHVC = pColor_in_out; + for (nI = 0; nI < nSamples; nI++, pHVC++) { + nT = (XcmsFloat) nI / (XcmsFloat) nSamples; + pHVC->spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + pHVC->spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + pHVC->spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + pHVC->format = XcmsRGBiFormat; + pHVC->pixel = pColor_in_out->pixel; + /* convert from RGB to HVC */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, pHVC, + &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* make sure to return the input hue */ + pHVC->spec.TekHVC.H = hue; + } + + return(XcmsSuccess); +} diff --git a/src/xcms/HVCWpAj.c b/src/xcms/HVCWpAj.c new file mode 100644 index 0000000..76e64c0 --- /dev/null +++ b/src/xcms/HVCWpAj.c @@ -0,0 +1,118 @@ +/* $Xorg: HVCWpAj.c,v 1.3 2000/08/17 19:44:37 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. TekColor is a + * trademark of Tektronix, Inc. The term "TekHVC" designates a particular + * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent + * foreign patents pending). Permission is hereby granted to use, copy, + * modify, sell, and otherwise distribute this software and its + * documentation for any purpose and without fee, provided that: + * + * 1. This copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and any modification thereof and in + * supporting documentation; + * 2. Any color-handling application which displays TekHVC color + * cooordinates identifies these as TekHVC color coordinates in any + * interface that displays these coordinates and in any associated + * documentation; + * 3. The term "TekHVC" is always used, and is only used, in association + * with the mathematical derivations of the TekHVC Color Space, + * including those provided in this file and any equivalent pathways and + * mathematical derivations, regardless of digital (e.g., floating point + * or integer) representation. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * DESCRIPTION + * TekHVCWpAj.c + * + * DESCRIPTION + * This file contains routine(s) that support white point + * adjustment of color specifications in the TekHVC color + * space. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern Status _XcmsConvertColorsWithWhitePt(); +extern XcmsColorSpace XcmsTekHVCColorSpace; + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsTekHVCWhiteShiftColors + * + * SYNOPSIS + */ +Status +XcmsTekHVCWhiteShiftColors(ccc, pWhitePtFrom, pWhitePtTo, destSpecFmt, + pColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pWhitePtFrom; + XcmsColor *pWhitePtTo; + XcmsColorFormat destSpecFmt; + XcmsColor *pColors_in_out; + unsigned int nColors; + Bool *pCompressed; +/* + * DESCRIPTION + * Convert color specifications in an array of XcmsColor structures + * for differences in white points. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression, + * XcmsSuccessWithCompression if succeeded with + * gamut compression. + */ +{ + if (pWhitePtFrom == NULL || pWhitePtTo == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Insure TekHVC installed + */ + if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Convert to TekHVC using pWhitePtFrom + * We can ignore return value for compression because we are converting + * to XcmsTekHVCFormat which is device-independent, not device-dependent. + */ + if (_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePtFrom, + nColors, XcmsTekHVCFormat, pCompressed) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Convert from TekHVC to destSpecFmt using pWhitePtTo + */ + return(_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePtTo, + nColors, destSpecFmt, pCompressed)); +} diff --git a/src/xcms/IdOfPr.c b/src/xcms/IdOfPr.c new file mode 100644 index 0000000..d84986e --- /dev/null +++ b/src/xcms/IdOfPr.c @@ -0,0 +1,111 @@ +/* $Xorg: IdOfPr.c,v 1.3 2000/08/17 19:44:38 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsIdOfPr.c + * + * DESCRIPTION + * Source for XcmsFormatOfPrefix() + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern XcmsColorSpace **_XcmsDIColorSpaces; +extern XcmsColorSpace **_XcmsDDColorSpaces; +void _XcmsCopyISOLatin1Lowered(); + + +/* + * NAME + * XcmsFormatOfPrefix + * + * SYNOPSIS + */ +XcmsColorFormat +XcmsFormatOfPrefix(prefix) + char *prefix; +/* + * DESCRIPTION + * Returns the Color Space ID for the specified prefix + * if the color space is found in the Color Conversion + * Context. + * + * RETURNS + * Color Space ID if found; zero otherwise. + */ +{ + XcmsColorSpace **papColorSpaces; + char string_buf[64]; + char *string_lowered; + int len; + + /* + * While copying prefix to string_lowered, convert to lowercase + */ + if ((len = strlen(prefix)) >= sizeof(string_buf)) { + string_lowered = (char *) Xmalloc(len+1); + } else { + string_lowered = string_buf; + } + _XcmsCopyISOLatin1Lowered(string_lowered, prefix); + + /* + * First try Device-Independent color spaces + */ + papColorSpaces = _XcmsDIColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if (strcmp((*papColorSpaces)->prefix, string_lowered) == 0) { + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return((*papColorSpaces)->id); + } + papColorSpaces++; + } + } + + /* + * Next try Device-Dependent color spaces + */ + papColorSpaces = _XcmsDDColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if (strcmp((*papColorSpaces)->prefix, string_lowered) == 0) { + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return((*papColorSpaces)->id); + } + papColorSpaces++; + } + } + + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return(XcmsUndefinedFormat); +} diff --git a/src/xcms/LRGB.c b/src/xcms/LRGB.c new file mode 100644 index 0000000..5b8b806 --- /dev/null +++ b/src/xcms/LRGB.c @@ -0,0 +1,1813 @@ +/* $Xorg: LRGB.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsLRGB.c + * + * DESCRIPTION + * This file contains the conversion routines: + * 1. CIE XYZ to RGB intensity + * 2. RGB intensity to device RGB + * 3. device RGB to RGB intensity + * 4. RGB intensity to CIE XYZ + * + */ + +#include <stdio.h> +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +#ifdef __STDC__ +#define Const const +#else +#define Const /**/ +#endif + +/* + * EXTERNS + * External declarations required locally to this package + * that are not already declared in any of the included header + * files (external includes or internal includes). + */ +extern char _XcmsRGB_prefix[]; +extern char _XcmsRGBi_prefix[]; +extern unsigned long _XcmsGetElement(); +extern void _XcmsFreeIntensityMaps(); + + +/* + * LOCAL DEFINES + * #define declarations local to this package. + */ +#define EPS 0.001 +#ifndef MIN +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif /* MIN */ +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif /* MAX */ +#ifndef MIN3 +#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) +#endif /* MIN3 */ +#ifndef MAX3 +#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) +#endif /* MAX3 */ + +/* + * LOCAL TYPEDEFS + * typedefs local to this package (for use with local vars). + * + */ + +/* + * FORWARD DECLARATIONS + */ +static void LINEAR_RGB_FreeSCCData(); +static int LINEAR_RGB_InitSCCData(); +static int XcmsLRGB_RGB_ParseString(); +static int XcmsLRGB_RGBi_ParseString(); +Status _XcmsGetTableType0(); +Status _XcmsGetTableType1(); + +/* + * LOCALS VARIABLES + * Variables local to this package. + * Usage example: + * static int ExampleLocalVar; + */ + +static unsigned short Const MASK[17] = { + 0x0000, /* 0 bitsPerRGB */ + 0x8000, /* 1 bitsPerRGB */ + 0xc000, /* 2 bitsPerRGB */ + 0xe000, /* 3 bitsPerRGB */ + 0xf000, /* 4 bitsPerRGB */ + 0xf800, /* 5 bitsPerRGB */ + 0xfc00, /* 6 bitsPerRGB */ + 0xfe00, /* 7 bitsPerRGB */ + 0xff00, /* 8 bitsPerRGB */ + 0xff80, /* 9 bitsPerRGB */ + 0xffc0, /* 10 bitsPerRGB */ + 0xffe0, /* 11 bitsPerRGB */ + 0xfff0, /* 12 bitsPerRGB */ + 0xfff8, /* 13 bitsPerRGB */ + 0xfffc, /* 14 bitsPerRGB */ + 0xfffe, /* 15 bitsPerRGB */ + 0xffff /* 16 bitsPerRGB */ +}; + + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsRGBFormat + * to XcmsCIEXYZFormat. + */ +static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = { + XcmsRGBToRGBi, + XcmsRGBiToCIEXYZ, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsCIEXYZFormat + * to XcmsRGBFormat. + */ +static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = { + XcmsCIEXYZToRGBi, + XcmsRGBiToRGB, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsRGBiFormat + * to XcmsCIEXYZFormat. + */ +static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = { + XcmsRGBiToCIEXYZ, + NULL +}; + + /* + * A NULL terminated array of function pointers that when applied + * in series will convert an XcmsColor structure from XcmsCIEXYZFormat + * to XcmsRGBiFormat. + */ +static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = { + XcmsCIEXYZToRGBi, + NULL +}; + + /* + * RGBi Color Spaces + */ +XcmsColorSpace XcmsRGBiColorSpace = + { + _XcmsRGBi_prefix, /* prefix */ + XcmsRGBiFormat, /* id */ + XcmsLRGB_RGBi_ParseString, /* parseString */ + Fl_RGBi_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_RGBi, /* from_CIEXYZ */ + 1 + }; + + /* + * RGB Color Spaces + */ +XcmsColorSpace XcmsRGBColorSpace = + { + _XcmsRGB_prefix, /* prefix */ + XcmsRGBFormat, /* id */ + XcmsLRGB_RGB_ParseString, /* parseString */ + Fl_RGB_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_RGB, /* from_CIEXYZ */ + 1 + }; + + /* + * Device-Independent Color Spaces known to the + * LINEAR_RGB Screen Color Characteristics Function Set. + */ +static XcmsColorSpace *DDColorSpaces[] = { + &XcmsRGBColorSpace, + &XcmsRGBiColorSpace, + NULL +}; + + +/* + * GLOBALS + * Variables declared in this package that are allowed + * to be used globally. + */ + + /* + * LINEAR_RGB Screen Color Characteristics Function Set. + */ +XcmsFunctionSet XcmsLinearRGBFunctionSet = + { + &DDColorSpaces[0], /* pDDColorSpaces */ + LINEAR_RGB_InitSCCData, /* pInitScrnFunc */ + LINEAR_RGB_FreeSCCData /* pFreeSCCData */ + }; + +/* + * DESCRIPTION + * Contents of Default SCCData should be replaced if other + * data should be used as default. + * + * + */ + +/* + * NAME Tektronix 19" (Sony) CRT + * PART_NUMBER 119-2451-00 + * MODEL Tek4300, Tek4800 + */ + +static IntensityRec Const Default_RGB_RedTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + 0x0000, 0.000000, + 0x0909, 0.000000, + 0x0a0a, 0.000936, + 0x0f0f, 0.001481, + 0x1414, 0.002329, + 0x1919, 0.003529, + 0x1e1e, 0.005127, + 0x2323, 0.007169, + 0x2828, 0.009699, + 0x2d2d, 0.012759, + 0x3232, 0.016392, + 0x3737, 0.020637, + 0x3c3c, 0.025533, + 0x4141, 0.031119, + 0x4646, 0.037431, + 0x4b4b, 0.044504, + 0x5050, 0.052373, + 0x5555, 0.061069, + 0x5a5a, 0.070624, + 0x5f5f, 0.081070, + 0x6464, 0.092433, + 0x6969, 0.104744, + 0x6e6e, 0.118026, + 0x7373, 0.132307, + 0x7878, 0.147610, + 0x7d7d, 0.163958, + 0x8282, 0.181371, + 0x8787, 0.199871, + 0x8c8c, 0.219475, + 0x9191, 0.240202, + 0x9696, 0.262069, + 0x9b9b, 0.285089, + 0xa0a0, 0.309278, + 0xa5a5, 0.334647, + 0xaaaa, 0.361208, + 0xafaf, 0.388971, + 0xb4b4, 0.417945, + 0xb9b9, 0.448138, + 0xbebe, 0.479555, + 0xc3c3, 0.512202, + 0xc8c8, 0.546082, + 0xcdcd, 0.581199, + 0xd2d2, 0.617552, + 0xd7d7, 0.655144, + 0xdcdc, 0.693971, + 0xe1e1, 0.734031, + 0xe6e6, 0.775322, + 0xebeb, 0.817837, + 0xf0f0, 0.861571, + 0xf5f5, 0.906515, + 0xfafa, 0.952662, + 0xffff, 1.000000 +}; + +static IntensityRec Const Default_RGB_GreenTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + 0x0000, 0.000000, + 0x1313, 0.000000, + 0x1414, 0.000832, + 0x1919, 0.001998, + 0x1e1e, 0.003612, + 0x2323, 0.005736, + 0x2828, 0.008428, + 0x2d2d, 0.011745, + 0x3232, 0.015740, + 0x3737, 0.020463, + 0x3c3c, 0.025960, + 0x4141, 0.032275, + 0x4646, 0.039449, + 0x4b4b, 0.047519, + 0x5050, 0.056520, + 0x5555, 0.066484, + 0x5a5a, 0.077439, + 0x5f5f, 0.089409, + 0x6464, 0.102418, + 0x6969, 0.116485, + 0x6e6e, 0.131625, + 0x7373, 0.147853, + 0x7878, 0.165176, + 0x7d7d, 0.183604, + 0x8282, 0.203140, + 0x8787, 0.223783, + 0x8c8c, 0.245533, + 0x9191, 0.268384, + 0x9696, 0.292327, + 0x9b9b, 0.317351, + 0xa0a0, 0.343441, + 0xa5a5, 0.370580, + 0xaaaa, 0.398747, + 0xafaf, 0.427919, + 0xb4b4, 0.458068, + 0xb9b9, 0.489165, + 0xbebe, 0.521176, + 0xc3c3, 0.554067, + 0xc8c8, 0.587797, + 0xcdcd, 0.622324, + 0xd2d2, 0.657604, + 0xd7d7, 0.693588, + 0xdcdc, 0.730225, + 0xe1e1, 0.767459, + 0xe6e6, 0.805235, + 0xebeb, 0.843491, + 0xf0f0, 0.882164, + 0xf5f5, 0.921187, + 0xfafa, 0.960490, + 0xffff, 1.000000 +}; + +static IntensityRec Const Default_RGB_BlueTuples[] = { + /* {unsigned short value, XcmsFloat intensity} */ + 0x0000, 0.000000, + 0x0e0e, 0.000000, + 0x0f0f, 0.001341, + 0x1414, 0.002080, + 0x1919, 0.003188, + 0x1e1e, 0.004729, + 0x2323, 0.006766, + 0x2828, 0.009357, + 0x2d2d, 0.012559, + 0x3232, 0.016424, + 0x3737, 0.021004, + 0x3c3c, 0.026344, + 0x4141, 0.032489, + 0x4646, 0.039481, + 0x4b4b, 0.047357, + 0x5050, 0.056154, + 0x5555, 0.065903, + 0x5a5a, 0.076634, + 0x5f5f, 0.088373, + 0x6464, 0.101145, + 0x6969, 0.114968, + 0x6e6e, 0.129862, + 0x7373, 0.145841, + 0x7878, 0.162915, + 0x7d7d, 0.181095, + 0x8282, 0.200386, + 0x8787, 0.220791, + 0x8c8c, 0.242309, + 0x9191, 0.264937, + 0x9696, 0.288670, + 0x9b9b, 0.313499, + 0xa0a0, 0.339410, + 0xa5a5, 0.366390, + 0xaaaa, 0.394421, + 0xafaf, 0.423481, + 0xb4b4, 0.453547, + 0xb9b9, 0.484592, + 0xbebe, 0.516587, + 0xc3c3, 0.549498, + 0xc8c8, 0.583291, + 0xcdcd, 0.617925, + 0xd2d2, 0.653361, + 0xd7d7, 0.689553, + 0xdcdc, 0.726454, + 0xe1e1, 0.764013, + 0xe6e6, 0.802178, + 0xebeb, 0.840891, + 0xf0f0, 0.880093, + 0xf5f5, 0.919723, + 0xfafa, 0.959715, + 0xffff, 1.00000 +}; + +static IntensityTbl Default_RGB_RedTbl = { + /* IntensityRec *pBase */ + (IntensityRec *) Default_RGB_RedTuples, + /* unsigned int nEntries */ + 52 +}; + +static IntensityTbl Default_RGB_GreenTbl = { + /* IntensityRec *pBase */ + (IntensityRec *)Default_RGB_GreenTuples, + /* unsigned int nEntries */ + 50 +}; + +static IntensityTbl Default_RGB_BlueTbl = { + /* IntensityRec *pBase */ + (IntensityRec *)Default_RGB_BlueTuples, + /* unsigned int nEntries */ + 51 +}; + +static LINEAR_RGB_SCCData Default_RGB_SCCData = { + + /* XcmsFloat XYZtoRGBmatrix[3][3] */ + 3.48340481253539000, -1.52176374927285200, -0.55923133354049780, + -1.07152751306193600, 1.96593795204372400, 0.03673691339553462, + 0.06351179790497788, -0.20020501000496480, 0.81070942031648220, + + /* XcmsFloat RGBtoXYZmatrix[3][3] */ + 0.38106149108714790, 0.32025712365352110, 0.24834578525933100, + 0.20729745115140850, 0.68054638776373240, 0.11215616108485920, + 0.02133944350088028, 0.14297193020246480, 1.24172892629665500, + + /* IntensityTbl *pRedTbl */ + &Default_RGB_RedTbl, + + /* IntensityTbl *pGreenTbl */ + &Default_RGB_GreenTbl, + + /* IntensityTbl *pBlueTbl */ + &Default_RGB_BlueTbl +}; + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * LINEAR_RGB_InitSCCData() + * + * SYNOPSIS + */ +static Status +LINEAR_RGB_InitSCCData(dpy, screenNumber, pPerScrnInfo) + Display *dpy; + int screenNumber; + XcmsPerScrnInfo *pPerScrnInfo; +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + Atom CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True); + Atom MatrixAtom = XInternAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True); + int format_return, count, cType, nTables; + unsigned long nitems, nbytes_return; + char *property_return, *pChar; + XcmsFloat *pValue; +#ifdef ALLDEBUG + IntensityRec *pIRec; +#endif /* ALLDEBUG */ + VisualID visualID; + + LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData; + XcmsIntensityMap *pNewMap; + + /* + * Allocate memory for pScreenData + */ + if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *) + Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) { + return(XcmsFailure); + } + + /* + * 1. Get the XYZ->RGB and RGB->XYZ matrices + */ + + if (MatrixAtom == None || + !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom, + &format_return, &nitems, &nbytes_return, &property_return) || + nitems != 18 || format_return != 32) { + /* + * As per the XDCCC, there must be 18 data items and each must be + * in 32 bits ! + */ + goto FreeSCCData; + + } else { + + /* + * RGBtoXYZ and XYZtoRGB matrices + */ + pValue = (XcmsFloat *) pScreenData; + pChar = property_return; + for (count = 0; count < 18; count++) { + *pValue++ = (long)_XcmsGetElement(format_return, &pChar, + &nitems) / (XcmsFloat)XDCCC_NUMBER; + } + Xfree ((char *)property_return); + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X = + pScreenData->RGBtoXYZmatrix[0][0] + + pScreenData->RGBtoXYZmatrix[0][1] + + pScreenData->RGBtoXYZmatrix[0][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = + pScreenData->RGBtoXYZmatrix[1][0] + + pScreenData->RGBtoXYZmatrix[1][1] + + pScreenData->RGBtoXYZmatrix[1][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z = + pScreenData->RGBtoXYZmatrix[2][0] + + pScreenData->RGBtoXYZmatrix[2][1] + + pScreenData->RGBtoXYZmatrix[2][2]; + + /* + * Compute the Screen White Point + */ + if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) ) + || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) { + goto FreeSCCData; + } else { + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0; + } + pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat; + pPerScrnInfo->screenWhitePt.pixel = 0; + +#ifdef PDEBUG + printf ("RGB to XYZ Matrix values:\n"); + printf (" %f %f %f\n %f %f %f\n %f %f %f\n", + pScreenData->RGBtoXYZmatrix[0][0], + pScreenData->RGBtoXYZmatrix[0][1], + pScreenData->RGBtoXYZmatrix[0][2], + pScreenData->RGBtoXYZmatrix[1][0], + pScreenData->RGBtoXYZmatrix[1][1], + pScreenData->RGBtoXYZmatrix[1][2], + pScreenData->RGBtoXYZmatrix[2][0], + pScreenData->RGBtoXYZmatrix[2][1], + pScreenData->RGBtoXYZmatrix[2][2]); + printf ("XYZ to RGB Matrix values:\n"); + printf (" %f %f %f\n %f %f %f\n %f %f %f\n", + pScreenData->XYZtoRGBmatrix[0][0], + pScreenData->XYZtoRGBmatrix[0][1], + pScreenData->XYZtoRGBmatrix[0][2], + pScreenData->XYZtoRGBmatrix[1][0], + pScreenData->XYZtoRGBmatrix[1][1], + pScreenData->XYZtoRGBmatrix[1][2], + pScreenData->XYZtoRGBmatrix[2][0], + pScreenData->XYZtoRGBmatrix[2][1], + pScreenData->XYZtoRGBmatrix[2][2]); + printf ("Screen White Pt value: %f %f %f\n", + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X, + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y, + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z); +#endif /* PDEBUG */ + } + + /* + * 2. Get the Intensity Profile + */ + if (CorrectAtom == None || + !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom, + &format_return, &nitems, &nbytes_return, &property_return)) { + Xfree ((char *)property_return); + goto FreeSCCData; + } + + pChar = property_return; + + while (nitems) { + switch (format_return) { + case 8: + /* + * Must have at least: + * VisualID0 + * VisualID1 + * VisualID2 + * VisualID3 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 9) { + Xfree ((char *)property_return); + goto FreeSCCData; + } + count = 3; + break; + case 16: + /* + * Must have at least: + * VisualID0 + * VisualID3 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 7) { + Xfree ((char *)property_return); + goto FreeSCCData; + } + count = 1; + break; + case 32: + /* + * Must have at least: + * VisualID0 + * type + * count + * length + * intensity1 + * intensity2 + */ + if (nitems < 6) { + Xfree ((char *)property_return); + goto FreeSCCData; + } + count = 0; + break; + default: + Xfree ((char *)property_return); + goto FreeSCCData; + } + + /* + * Get VisualID + */ + visualID = _XcmsGetElement(format_return, &pChar, &nitems); + while (count--) { + visualID = visualID << format_return; + visualID |= _XcmsGetElement(format_return, &pChar, &nitems); + } + + if (visualID == 0) { + /* + * This is a shared intensity table + */ + pScreenData = pScreenDefaultData; + } else { + /* + * This is a per-Visual intensity table + */ + if (!(pScreenData = (LINEAR_RGB_SCCData *) + Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) { + return(XcmsFailure); + } + /* copy matrices */ + memcpy((char *)pScreenData, (char *)pScreenDefaultData, + 18 * sizeof(XcmsFloat)); + + /* Create, initialize, and add map */ + if (!(pNewMap = (XcmsIntensityMap *) + Xcalloc (1, sizeof(XcmsIntensityMap)))) { + Xfree((char *)pScreenData); + return(XcmsFailure); + } + pNewMap->visualID = visualID; + pNewMap->screenData = (XPointer)pScreenData; + pNewMap->pFreeScreenData = LINEAR_RGB_FreeSCCData; + pNewMap->pNext = + (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; + dpy->cms.perVisualIntensityMaps = (XPointer)pNewMap; + dpy->free_funcs->intensityMaps = _XcmsFreeIntensityMaps; + } + + cType = _XcmsGetElement(format_return, &pChar, &nitems); + nTables = _XcmsGetElement(format_return, &pChar, &nitems); + + if (cType == 0) { + + /* Red Intensity Table */ + if (!(pScreenData->pRedTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeSCCData; + } + if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeRedTbl; + } + + if (nTables == 1) { + /* Green Intensity Table */ + pScreenData->pGreenTbl = pScreenData->pRedTbl; + /* Blue Intensity Table */ + pScreenData->pBlueTbl = pScreenData->pRedTbl; + } else { + /* Green Intensity Table */ + if (!(pScreenData->pGreenTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeRedTblElements; + } + if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeGreenTbl; + } + + /* Blue Intensity Table */ + if (!(pScreenData->pBlueTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeGreenTblElements; + } + if (_XcmsGetTableType0(pScreenData->pBlueTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeBlueTbl; + } + } + } else if (cType == 1) { + /* Red Intensity Table */ + if (!(pScreenData->pRedTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeSCCData; + } + if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeRedTbl; + } + + if (nTables == 1) { + + /* Green Intensity Table */ + pScreenData->pGreenTbl = pScreenData->pRedTbl; + /* Blue Intensity Table */ + pScreenData->pBlueTbl = pScreenData->pRedTbl; + + } else { + + /* Green Intensity Table */ + if (!(pScreenData->pGreenTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeRedTblElements; + } + if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeGreenTbl; + } + + /* Blue Intensity Table */ + if (!(pScreenData->pBlueTbl = (IntensityTbl *) + Xcalloc (1, sizeof(IntensityTbl)))) { + goto FreeBlueTblElements; + } + if (_XcmsGetTableType1(pScreenData->pBlueTbl, format_return, &pChar, + &nitems) == XcmsFailure) { + goto FreeBlueTbl; + } + } + } else { + Xfree ((char *)property_return); + goto FreeSCCData; + } + +#ifdef ALLDEBUG + printf ("Intensity Table RED %d\n", pScreenData->pRedTbl->nEntries); + pIRec = (IntensityRec *) pScreenData->pRedTbl->pBase; + for (count = 0; count < pScreenData->pRedTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + if (pScreenData->pGreenTbl->pBase != pScreenData->pRedTbl->pBase) { + printf ("Intensity Table GREEN %d\n", pScreenData->pGreenTbl->nEntries); + pIRec = (IntensityRec *)pScreenData->pGreenTbl->pBase; + for (count = 0; count < pScreenData->pGreenTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + } + if (pScreenData->pBlueTbl->pBase != pScreenData->pRedTbl->pBase) { + printf ("Intensity Table BLUE %d\n", pScreenData->pBlueTbl->nEntries); + pIRec = (IntensityRec *) pScreenData->pBlueTbl->pBase; + for (count = 0; count < pScreenData->pBlueTbl->nEntries; count++, pIRec++) { + printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity); + } + } +#endif /* ALLDEBUG */ + } + + Xfree ((char *)property_return); + + /* Free the old memory and use the new structure created. */ + LINEAR_RGB_FreeSCCData(pPerScrnInfo->screenData); + + pPerScrnInfo->functionSet = (XPointer) &XcmsLinearRGBFunctionSet; + + pPerScrnInfo->screenData = (XPointer) pScreenData; + + pPerScrnInfo->state = XcmsInitSuccess; + + return(XcmsSuccess); + +FreeBlueTblElements: + Xfree((char *)pScreenData->pBlueTbl->pBase); + +FreeBlueTbl: + Xfree((char *)pScreenData->pBlueTbl); + +FreeGreenTblElements: + Xfree((char *)pScreenData->pBlueTbl->pBase); + +FreeGreenTbl: + Xfree((char *)pScreenData->pGreenTbl); + +FreeRedTblElements: + Xfree((char *)pScreenData->pRedTbl->pBase); + +FreeRedTbl: + Xfree((char *)pScreenData->pRedTbl); + +FreeSCCData: + Xfree((char *)pScreenData); + pPerScrnInfo->state = XcmsInitNone; + return(XcmsFailure); +} + + +/* + * NAME + * LINEAR_RGB_FreeSCCData() + * + * SYNOPSIS + */ +static void +LINEAR_RGB_FreeSCCData(pScreenDataTemp) + XPointer pScreenDataTemp; +/* + * DESCRIPTION + * + * RETURNS + * 0 if failed. + * 1 if succeeded with no modifications. + * + */ +{ + LINEAR_RGB_SCCData *pScreenData = (LINEAR_RGB_SCCData *) pScreenDataTemp; + + if (pScreenData && pScreenData != &Default_RGB_SCCData) { + if (pScreenData->pRedTbl) { + if (pScreenData->pGreenTbl) { + if (pScreenData->pRedTbl->pBase != + pScreenData->pGreenTbl->pBase) { + if (pScreenData->pGreenTbl->pBase) { + Xfree ((char *)pScreenData->pGreenTbl->pBase); + } + } + if (pScreenData->pGreenTbl != pScreenData->pRedTbl) { + Xfree ((char *)pScreenData->pGreenTbl); + } + } + if (pScreenData->pBlueTbl) { + if (pScreenData->pRedTbl->pBase != + pScreenData->pBlueTbl->pBase) { + if (pScreenData->pBlueTbl->pBase) { + Xfree ((char *)pScreenData->pBlueTbl->pBase); + } + } + if (pScreenData->pBlueTbl != pScreenData->pRedTbl) { + Xfree ((char *)pScreenData->pBlueTbl); + } + } + if (pScreenData->pRedTbl->pBase) { + Xfree ((char *)pScreenData->pRedTbl->pBase); + } + Xfree ((char *)pScreenData->pRedTbl); + } + Xfree ((char *)pScreenData); + } +} + + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsGetTableType0 + * + * SYNOPSIS + */ +Status +_XcmsGetTableType0(pTbl, format, pChar, pCount) + IntensityTbl *pTbl; + int format; + char **pChar; + unsigned long *pCount; +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + unsigned int nElements; + IntensityRec *pIRec; + + nElements = pTbl->nEntries = + _XcmsGetElement(format, pChar, pCount) + 1; + if (!(pIRec = pTbl->pBase = (IntensityRec *) + Xcalloc (nElements, sizeof(IntensityRec)))) { + return(XcmsFailure); + } + + switch (format) { + case 8: + for (; nElements--; pIRec++) { + /* 0xFFFF/0xFF = 0x101 */ + pIRec->value = _XcmsGetElement (format, pChar, pCount) * 0x101; + pIRec->intensity = + _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0; + } + break; + case 16: + for (; nElements--; pIRec++) { + pIRec->value = _XcmsGetElement (format, pChar, pCount); + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)65535.0; + } + break; + case 32: + for (; nElements--; pIRec++) { + pIRec->value = _XcmsGetElement (format, pChar, pCount); + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)4294967295.0; + } + break; + default: + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * _XcmsGetTableType1 + * + * SYNOPSIS + */ +Status +_XcmsGetTableType1(pTbl, format, pChar, pCount) + IntensityTbl *pTbl; + int format; + char **pChar; + unsigned long *pCount; +/* + * DESCRIPTION + * + * RETURNS + * XcmsFailure if failed. + * XcmsSuccess if succeeded. + * + */ +{ + int count; + unsigned int max_index; + IntensityRec *pIRec; + + max_index = _XcmsGetElement(format, pChar, pCount); + pTbl->nEntries = max_index + 1; + if (!(pIRec = pTbl->pBase = (IntensityRec *) + Xcalloc (max_index+1, sizeof(IntensityRec)))) { + return(XcmsFailure); + } + + switch (format) { + case 8: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)255.0; + } + break; + case 16: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)65535.0; + } + break; + case 32: + for (count = 0; count < max_index+1; count++, pIRec++) { + pIRec->value = (count * 65535) / max_index; + pIRec->intensity = _XcmsGetElement (format, pChar, pCount) + / (XcmsFloat)4294967295.0; + } + break; + default: + return(XcmsFailure); + } + + return(XcmsSuccess); +} + + +/* + * NAME + * ValueCmp + * + * SYNOPSIS + */ +int +_XcmsValueCmp (p1, p2) + IntensityRec *p1, *p2; +/* + * DESCRIPTION + * Compares the value component of two IntensityRec + * structures. + * + * RETURNS + * 0 if p1->value is equal to p2->value + * < 0 if p1->value is less than p2->value + * > 0 if p1->value is greater than p2->value + * + */ +{ + return (p1->value - p2->value); +} + + +/* + * NAME + * IntensityCmp + * + * SYNOPSIS + */ +int +_XcmsIntensityCmp (p1, p2) + IntensityRec *p1, *p2; +/* + * DESCRIPTION + * Compares the intensity component of two IntensityRec + * structures. + * + * RETURNS + * 0 if equal; + * < 0 if first precedes second + * > 0 if first succeeds second + * + */ +{ + if (p1->intensity < p2->intensity) { + return (-1); + } + if (p1->intensity > p2->intensity) { + return (XcmsSuccess); + } + return (XcmsFailure); +} + +/* + * NAME + * ValueInterpolation + * + * SYNOPSIS + */ +/* ARGSUSED */ +int +_XcmsValueInterpolation (key, lo, hi, answer, bitsPerRGB) + IntensityRec *key, *lo, *hi, *answer; + int bitsPerRGB; +/* + * DESCRIPTION + * Based on a given value, performs a linear interpolation + * on the intensities between two IntensityRec structures. + * Note that the bitsPerRGB parameter is ignored. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + */ +{ + XcmsFloat ratio; + + ratio = ((XcmsFloat)key->value - (XcmsFloat)lo->value) / + ((XcmsFloat)hi->value - (XcmsFloat)lo->value); + answer->value = key->value; + answer->intensity = (hi->intensity - lo->intensity) * ratio; + answer->intensity += lo->intensity; + return (XcmsSuccess); +} + +/* + * NAME + * IntensityInterpolation + * + * SYNOPSIS + */ +int +_XcmsIntensityInterpolation (key, lo, hi, answer, bitsPerRGB) + IntensityRec *key, *lo, *hi, *answer; + int bitsPerRGB; +/* + * DESCRIPTION + * Based on a given intensity, performs a linear interpolation + * on the values between two IntensityRec structures. + * The bitsPerRGB parameter is necessary to perform rounding + * to the correct number of significant bits. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + */ +{ + XcmsFloat ratio; + long target, up, down; + int shift = 16 - bitsPerRGB; + int max_color = (1 << bitsPerRGB) - 1; + + ratio = (key->intensity - lo->intensity) / (hi->intensity - lo->intensity); + answer->intensity = key->intensity; + target = hi->value - lo->value; + target *= ratio; + target += lo->value; + + /* + * Ok now, lets find the closest in respects to bits per RGB + */ + up = ((target >> shift) * 0xFFFF) / max_color; + if (up < target) { + down = up; + up = (MIN((down >> shift) + 1, max_color) * 0xFFFF) / max_color; + } else { + down = (MAX((up >> shift) - 1, 0) * 0xFFFF) / max_color; + } + answer->value = ((up - target) < (target - down) ? up : down); + answer->value &= MASK[bitsPerRGB]; + return (XcmsSuccess); +} + + +/* + * NAME + * _XcmsTableSearch + * + * SYNOPSIS + */ +int +_XcmsTableSearch (key, bitsPerRGB, base, nel, nKeyPtrSize, compar, interpol, answer) + char *key; + int bitsPerRGB; + char *base; + unsigned nel; + unsigned nKeyPtrSize; + int (*compar)(); + int (*interpol)(); + char *answer; + +/* + * DESCRIPTION + * A binary search through the specificied table. + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + * + */ +{ + char *hi, *lo, *mid, *last; + int result; + + last = hi = base + ((nel - 1) * nKeyPtrSize); + mid = lo = base; + + /* use only the significants bits, then scale into 16 bits */ + ((IntensityRec *)key)->value = ((unsigned long) + (((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF) + / ((1 << bitsPerRGB) - 1); + + /* Special case so that zero intensity always maps to zero value */ + if ((*compar) (key,lo) <= 0) { + memcpy (answer, lo, nKeyPtrSize); + ((IntensityRec *)answer)->value &= MASK[bitsPerRGB]; + return XcmsSuccess; + } + while (mid != last) { + last = mid; + mid = lo + (((unsigned)(hi - lo) / nKeyPtrSize) / 2) * nKeyPtrSize; + result = (*compar) (key, mid); + if (result == 0) { + + memcpy(answer, mid, nKeyPtrSize); + ((IntensityRec *)answer)->value &= MASK[bitsPerRGB]; + return (XcmsSuccess); + } else if (result < 0) { + hi = mid; + } else { + lo = mid; + } + } + + /* + * If we got to here, we didn't find a solution, so we + * need to apply interpolation. + */ + return ((*interpol)(key, lo, hi, answer, bitsPerRGB)); +} + + +/* + * NAME + * _XcmsMatVec - multiply a 3 x 3 by a 3 x 1 vector + * + * SYNOPSIS + */ +void _XcmsMatVec(pMat, pIn, pOut) + XcmsFloat *pMat, *pIn, *pOut; +/* + * DESCRIPTION + * Multiply the passed vector by the passed matrix to return a + * vector. Matrix is 3x3, vectors are of length 3. + * + * RETURNS + * void + */ +{ + int i, j; + + for (i = 0; i < 3; i++) { + pOut[i] = 0.0; + for (j = 0; j < 3; j++) + pOut[i] += *(pMat+(i*3)+j) * pIn[j]; + } +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + + +/* + * NAME + * XcmsLRGB_RGB_ParseString + * + * SYNOPSIS + */ +static int +XcmsLRGB_RGB_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsRGBFormat. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + register int n, i; + unsigned short r, g, b; + char c; + char *pchar; + unsigned short *pShort; + + /* + * Check for old # format + */ + if (*spec == '#') { + /* + * Attempt to parse the value portion. + */ + spec++; + n = strlen(spec); + if (n != 3 && n != 6 && n != 9 && n != 12) { + return(XcmsFailure); + } + + n /= 3; + g = b = 0; + do { + r = g; + g = b; + b = 0; + for (i = n; --i >= 0; ) { + c = *spec++; + b <<= 4; + if (c >= '0' && c <= '9') + b |= c - '0'; + /* assume string in lowercase + else if (c >= 'A' && c <= 'F') + b |= c - ('A' - 10); + */ + else if (c >= 'a' && c <= 'f') + b |= c - ('a' - 10); + else return (XcmsFailure); + } + } while (*spec != '\0'); + + /* + * Succeeded ! + */ + n <<= 2; + n = 16 - n; + /* shift instead of scale, to match old broken semantics */ + pColor->spec.RGB.red = r << n; + pColor->spec.RGB.green = g << n; + pColor->spec.RGB.blue = b << n; + } else { + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsRGB_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + spec += (n + 1); + pShort = &pColor->spec.RGB.red; + for (i = 0; i < 3; i++, pShort++, spec++) { + n = 0; + *pShort = 0; + while (*spec != '/' && *spec != '\0') { + if (++n > 4) { + return(XcmsFailure); + } + c = *spec++; + *pShort <<= 4; + if (c >= '0' && c <= '9') + *pShort |= c - '0'; + /* assume string in lowercase + else if (c >= 'A' && c <= 'F') + *pShort |= c - ('A' - 10); + */ + else if (c >= 'a' && c <= 'f') + *pShort |= c - ('a' - 10); + else return (XcmsFailure); + } + if (n == 0) + return (XcmsFailure); + if (n < 4) { + *pShort = ((unsigned long)*pShort * 0xFFFF) / ((1 << n*4) - 1); + } + } + } + pColor->format = XcmsRGBFormat; + pColor->pixel = 0; + return (XcmsSuccess); +} + + +/* + * NAME + * XcmsLRGB_RGBi_ParseString + * + * SYNOPSIS + */ +static int +XcmsLRGB_RGBi_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsRGBiFormat. + * The assumed RGBi string syntax is: + * RGBi:<r>/<g>/<b> + * Where r, g, and b are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsRGBi_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.RGBi.red, + &pColor->spec.RGBi.green, + &pColor->spec.RGBi.blue) != 3) { + return(XcmsFailure); + } + + /* + * Succeeded ! + */ + pColor->format = XcmsRGBiFormat; + pColor->pixel = 0; + return (XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEXYZToRGBi - convert CIE XYZ to RGB + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIEXYZToRGBi(ccc, pXcmsColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */ + unsigned int nColors; /* Number of colors */ + Bool *pCompressed; /* pointer to an array of Bool */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGB format to RGBi format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression. + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsFloat tmp[3]; + int hasCompressed = 0; + unsigned int i; + XcmsColor *pColor = pXcmsColors_in_out; + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + /* + * XcmsColors should be White Point Adjusted, if necessary, by now! + */ + + /* + * NEW!!! for extended gamut compression + * + * 1. Need to zero out pCompressed + * + * 2. Need to save initial address of pColor + * + * 3. Need to save initial address of pCompressed + */ + + for (i = 0; i < nColors; i++) { + + /* Make sure format is XcmsCIEXYZFormat */ + if (pColor->format != XcmsCIEXYZFormat) { + return(XcmsFailure); + } + + /* Multiply [A]-1 * [XYZ] to get RGB intensity */ + _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix, + (XcmsFloat *) &pColor->spec, tmp); + + if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) || + (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) { + + /* + * RGBi out of screen's gamut + */ + + if (ccc->gamutCompProc == NULL) { + /* + * Aha!! Here's that little trick that will allow + * gamut compression routines to get the out of bound + * RGBi. + */ + memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp)); + pColor->format = XcmsRGBiFormat; + return(XcmsFailure); + } else if ((*ccc->gamutCompProc)(ccc, pXcmsColors_in_out, nColors, + i, pCompressed) == 0) { + return(XcmsFailure); + } + + /* + * The gamut compression function should return colors in CIEXYZ + * Also check again to if the new color is within gamut. + */ + if (pColor->format != XcmsCIEXYZFormat) { + return(XcmsFailure); + } + _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix, + (XcmsFloat *) &pColor->spec, tmp); + if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) || + (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) { + return(XcmsFailure); + } + hasCompressed++; + } + memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp)); + /* These if statements are done to ensure the fudge factor is */ + /* is taken into account. */ + if (pColor->spec.RGBi.red < 0.0) { + pColor->spec.RGBi.red = 0.0; + } else if (pColor->spec.RGBi.red > 1.0) { + pColor->spec.RGBi.red = 1.0; + } + if (pColor->spec.RGBi.green < 0.0) { + pColor->spec.RGBi.green = 0.0; + } else if (pColor->spec.RGBi.green > 1.0) { + pColor->spec.RGBi.green = 1.0; + } + if (pColor->spec.RGBi.blue < 0.0) { + pColor->spec.RGBi.blue = 0.0; + } else if (pColor->spec.RGBi.blue > 1.0) { + pColor->spec.RGBi.blue = 1.0; + } + (pColor++)->format = XcmsRGBiFormat; + } + return (hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess); +} + + +/* + * NAME + * LINEAR_RGBi_to_CIEXYZ - convert RGBi to CIEXYZ + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBiToCIEXYZ(ccc, pXcmsColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */ + unsigned int nColors; /* Number of colors */ + Bool *pCompressed; /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGBi format to CIEXYZ format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsFloat tmp[3]; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + /* + * XcmsColors should be White Point Adjusted, if necessary, by now! + */ + + while (nColors--) { + + /* Multiply [A]-1 * [XYZ] to get RGB intensity */ + _XcmsMatVec((XcmsFloat *) pScreenData->RGBtoXYZmatrix, + (XcmsFloat *) &pXcmsColors_in_out->spec, tmp); + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)tmp, sizeof(tmp)); + (pXcmsColors_in_out++)->format = XcmsCIEXYZFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsRGBiToRGB + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBiToRGB(ccc, pXcmsColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */ + unsigned int nColors; /* Number of colors */ + Bool *pCompressed; /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGBi format to RGB format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression. + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsRGB tmpRGB; + IntensityRec keyIRec, answerIRec; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + while (nColors--) { + + /* Make sure format is XcmsRGBiFormat */ + if (pXcmsColors_in_out->format != XcmsRGBiFormat) { + return(XcmsFailure); + } + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.red; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pRedTbl->pBase, + (unsigned)pScreenData->pRedTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.red = answerIRec.value; + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.green; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pGreenTbl->pBase, + (unsigned)pScreenData->pGreenTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.green = answerIRec.value; + + keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.blue; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pBlueTbl->pBase, + (unsigned)pScreenData->pBlueTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGB.blue = answerIRec.value; + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGB, sizeof(XcmsRGB)); + (pXcmsColors_in_out++)->format = XcmsRGBFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsRGBToRGBi + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsRGBToRGBi(ccc, pXcmsColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */ + unsigned int nColors; /* Number of colors */ + Bool *pCompressed; /* pointer to a bit array */ +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from RGB format to RGBi format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + */ +{ + LINEAR_RGB_SCCData *pScreenData; + XcmsRGBi tmpRGBi; + IntensityRec keyIRec, answerIRec; + + /* + * pCompressed ignored in this function. + */ + + if (ccc == NULL) { + return(XcmsFailure); + } + + pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData; + + while (nColors--) { + + /* Make sure format is XcmsRGBFormat */ + if (pXcmsColors_in_out->format != XcmsRGBFormat) { + return(XcmsFailure); + } + + keyIRec.value = pXcmsColors_in_out->spec.RGB.red; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pRedTbl->pBase, + (unsigned)pScreenData->pRedTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.red = answerIRec.intensity; + + keyIRec.value = pXcmsColors_in_out->spec.RGB.green; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pGreenTbl->pBase, + (unsigned)pScreenData->pGreenTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.green = answerIRec.intensity; + + keyIRec.value = pXcmsColors_in_out->spec.RGB.blue; + if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb, + (char *)pScreenData->pBlueTbl->pBase, + (unsigned)pScreenData->pBlueTbl->nEntries, + (unsigned)sizeof(IntensityRec), + _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) { + return(XcmsFailure); + } + tmpRGBi.blue = answerIRec.intensity; + + memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGBi, sizeof(XcmsRGBi)); + (pXcmsColors_in_out++)->format = XcmsRGBiFormat; + } + return(XcmsSuccess); +} + +/* + * NAME + * _XcmsInitScrnDefaultInfo + * + * SYNOPSIS + */ +/* ARGSUSED */ +int +_XcmsLRGB_InitScrnDefault(dpy, screenNumber, pPerScrnInfo) + Display *dpy; + int screenNumber; + XcmsPerScrnInfo *pPerScrnInfo; +/* + * DESCRIPTION + * Given a display and screen number, this routine attempts + * to initialize the Xcms per Screen Info structure + * (XcmsPerScrnInfo) with defaults. + * + * RETURNS + * Returns zero if initialization failed; non-zero otherwise. + */ +{ + pPerScrnInfo->screenData = (XPointer)&Default_RGB_SCCData; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X = + Default_RGB_SCCData.RGBtoXYZmatrix[0][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[0][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[0][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = + Default_RGB_SCCData.RGBtoXYZmatrix[1][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[1][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[1][2]; + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z = + Default_RGB_SCCData.RGBtoXYZmatrix[2][0] + + Default_RGB_SCCData.RGBtoXYZmatrix[2][1] + + Default_RGB_SCCData.RGBtoXYZmatrix[2][2]; + if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) ) + || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) { + pPerScrnInfo->screenData = (XPointer)NULL; + pPerScrnInfo->state = XcmsInitNone; + return(0); + } + pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0; + pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat; + pPerScrnInfo->screenWhitePt.pixel = 0; + pPerScrnInfo->functionSet = (XPointer)&XcmsLinearRGBFunctionSet; + pPerScrnInfo->state = XcmsInitFailure; /* default initialization */ + return(1); +} diff --git a/src/xcms/Lab.c b/src/xcms/Lab.c new file mode 100644 index 0000000..7827d8e --- /dev/null +++ b/src/xcms/Lab.c @@ -0,0 +1,416 @@ +/* $Xorg: Lab.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * CIELab.c + * + * DESCRIPTION + * This file contains routines that support the CIE L*a*b* + * color space to include conversions to and from the CIE + * XYZ space. These conversions are from Principles of + * Color Technology Second Edition, Fred W. Billmeyer, Jr. + * and Max Saltzman, John Wiley & Sons, Inc., 1981. + * + * Note that the range for L* is 0 to 1. + */ + + +#include <X11/Xos.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + * Internal definitions that need NOT be exported to any package + * or program using this package. + */ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif +#define DIV16BY116 0.137931 + +/* + * EXTERNS + */ +extern char _XcmsCIELab_prefix[]; + + +/* + * FORWARD DECLARATIONS + */ + +static int CIELab_ParseString(); +static Status XcmsCIELab_ValidSpec(); + + +/* + * LOCAL VARIABLES + */ + + + /* + * NULL terminated list of functions applied to get from CIELab to CIEXYZ + */ +static XcmsConversionProc Fl_CIELab_to_CIEXYZ[] = { + XcmsCIELabToCIEXYZ, + NULL +}; + + /* + * NULL terminated list of functions applied to get from CIEXYZ to CIELab + */ +static XcmsConversionProc Fl_CIEXYZ_to_CIELab[] = { + XcmsCIEXYZToCIELab, + NULL +}; + + +/* + * GLOBALS + */ + /* + * CIE Lab Color Space + */ +XcmsColorSpace XcmsCIELabColorSpace = + { + _XcmsCIELab_prefix, /* prefix */ + XcmsCIELabFormat, /* id */ + CIELab_ParseString, /* parseString */ + Fl_CIELab_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_CIELab, /* from_CIEXYZ */ + 1 + }; + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIELab_ParseString + * + * SYNOPSIS + */ +static int +CIELab_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsCIELabFormat. + * The assumed CIELab string syntax is: + * CIELab:<L>/<a>/<b> + * Where L, a, and b are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsCIELab_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.CIELab.L_star, + &pColor->spec.CIELab.a_star, + &pColor->spec.CIELab.b_star) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsCIELabFormat; + pColor->pixel = 0; + + return(XcmsCIELab_ValidSpec(pColor)); +} + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELab_ValidSpec + * + * SYNOPSIS + */ +static Status +XcmsCIELab_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if color specification valid for CIE L*a*b*. + * + * RETURNS + * XcmsFailure if invalid, + * XcmsSuccess if valid. + * + */ +{ + if (pColor->format != XcmsCIELabFormat + || + (pColor->spec.CIELab.L_star < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIELab.L_star > 100.0 + XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIELabToCIEXYZ - convert CIELab to CIEXYZ + * + * SYNOPSIS + */ +Status +XcmsCIELabToCIEXYZ(ccc, pLab_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pLab_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIELab format to CIEXYZ format. + * + * WARNING: This routine assumes that Yn = 1.0; + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsCIEXYZ XYZ_return; + XcmsFloat tmpFloat, tmpL; + XcmsColor whitePt; + int i; + XcmsColor *pColor = pColors_in_out; + + /* + * Check arguments + */ + if (pLab_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEXYZ form, if not, convert it. + */ + if (pLab_WhitePt->format != XcmsCIEXYZFormat) { + /* Make a copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pLab_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, + (XcmsColor *)NULL, 1, XcmsCIEXYZFormat)) { + return(XcmsFailure); + } + pLab_WhitePt = &whitePt; + } + + /* + * Make sure it is a white point, i.e., Y == 1.0 + */ + if (pLab_WhitePt->spec.CIEXYZ.Y != 1.0) { + return (0); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is CIELab */ + if (!XcmsCIELab_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* Calculate Y: assume that Yn = 1.0 */ + tmpL = (pColor->spec.CIELab.L_star + 16.0) / 116.0; + XYZ_return.Y = tmpL * tmpL * tmpL; + + if (XYZ_return.Y < 0.008856) { + /* Calculate Y: assume that Yn = 1.0 */ + tmpL = pColor->spec.CIELab.L_star / 9.03292; + + /* Calculate X */ + XYZ_return.X = pLab_WhitePt->spec.CIEXYZ.X * + ((pColor->spec.CIELab.a_star / 3893.5) + tmpL); + /* Calculate Y */ + XYZ_return.Y = tmpL; + /* Calculate Z */ + XYZ_return.Z = pLab_WhitePt->spec.CIEXYZ.Z * + (tmpL - (pColor->spec.CIELab.b_star / 1557.4)); + } else { + /* Calculate X */ + tmpFloat = tmpL + (pColor->spec.CIELab.a_star / 5.0); + XYZ_return.X = pLab_WhitePt->spec.CIEXYZ.X * tmpFloat * tmpFloat * tmpFloat; + + /* Calculate Z */ + tmpFloat = tmpL - (pColor->spec.CIELab.b_star / 2.0); + XYZ_return.Z = pLab_WhitePt->spec.CIEXYZ.Z * tmpFloat * tmpFloat * tmpFloat; + } + + memcpy((char *)&pColor->spec.CIEXYZ, (char *)&XYZ_return, + sizeof(XcmsCIEXYZ)); + pColor->format = XcmsCIEXYZFormat; + } + + return (1); +} + + +/* + * NAME + * XcmsCIEXYZToCIELab - convert CIEXYZ to CIELab + * + * SYNOPSIS + */ +Status +XcmsCIEXYZToCIELab(ccc, pLab_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pLab_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIEXYZ format to CIELab format. + * + * WARNING: This routine assumes that Yn = 1.0; + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsCIELab Lab_return; + XcmsFloat fX_Xn, fY_Yn, fZ_Zn; + XcmsColor whitePt; + int i; + XcmsColor *pColor = pColors_in_out; + + /* + * Check arguments + */ + if (pLab_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEXYZ form, if not, convert it. + */ + if (pLab_WhitePt->format != XcmsCIEXYZFormat) { + /* Make a copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pLab_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, + 1, XcmsCIEXYZFormat)) { + return(XcmsFailure); + } + pLab_WhitePt = &whitePt; + } + + /* + * Make sure it is a white point, i.e., Y == 1.0 + */ + if (pLab_WhitePt->spec.CIEXYZ.Y != 1.0) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is CIELab */ + if (!_XcmsCIEXYZ_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* Calculate L*: assume Yn = 1.0 */ + if (pColor->spec.CIEXYZ.Y < 0.008856) { + fY_Yn = (0.07787 * pColor->spec.CIEXYZ.Y) + DIV16BY116; + /* note fY_Yn used to compute Lab_return.a below */ + Lab_return.L_star = 116.0 * (fY_Yn - DIV16BY116); + } else { + fY_Yn = (XcmsFloat)XCMS_CUBEROOT(pColor->spec.CIEXYZ.Y); + /* note fY_Yn used to compute Lab_return.a_star below */ + Lab_return.L_star = (116.0 * fY_Yn) - 16.0; + } + + /* Calculate f(X/Xn) */ + if ((fX_Xn = pColor->spec.CIEXYZ.X / pLab_WhitePt->spec.CIEXYZ.X) < 0.008856) { + fX_Xn = (0.07787 * fX_Xn) + DIV16BY116; + } else { + fX_Xn = (XcmsFloat) XCMS_CUBEROOT(fX_Xn); + } + + /* Calculate f(Z/Zn) */ + if ((fZ_Zn = pColor->spec.CIEXYZ.Z / pLab_WhitePt->spec.CIEXYZ.Z) < 0.008856) { + fZ_Zn = (0.07787 * fZ_Zn) + DIV16BY116; + } else { + fZ_Zn = (XcmsFloat) XCMS_CUBEROOT(fZ_Zn); + } + + Lab_return.a_star = 5.0 * (fX_Xn - fY_Yn); + Lab_return.b_star = 2.0 * (fY_Yn - fZ_Zn); + + memcpy((char *)&pColor->spec.CIELab, (char *)&Lab_return, + sizeof(XcmsCIELab)); + pColor->format = XcmsCIELabFormat; + } + + return(XcmsSuccess); +} diff --git a/src/xcms/LabGcC.c b/src/xcms/LabGcC.c new file mode 100644 index 0000000..0618dcb --- /dev/null +++ b/src/xcms/LabGcC.c @@ -0,0 +1,124 @@ +/* $Xorg: LabGcC.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELabGcC.c + * + * DESCRIPTION + * Source for XcmsCIELabClipuv() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabClipab - Reduce the chroma for a hue and L* + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELabClipab (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Reduce the Chroma for a specific hue and chroma to + * to bring the given color into the gamut of the + * specified device. As required of gamut compression + * functions, this routine returns pColor_in_out + * in XcmsCIEXYZFormat on successful completion. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsColor *pColor; + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < PseudoColor) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIELabFormat); + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } else { + if (pColor->format != XcmsCIELabFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIELabFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELabQueryMaxC(ccc, + degrees(XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star)), + pColor->spec.CIELab.L_star, + pColor) == XcmsFailure) { + return(XcmsFailure); + } + retval = _XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/LabGcL.c b/src/xcms/LabGcL.c new file mode 100644 index 0000000..bc6d20e --- /dev/null +++ b/src/xcms/LabGcL.c @@ -0,0 +1,176 @@ +/* $Xorg: LabGcL.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELabGcL.c + * + * DESCRIPTION + * Source for XcmsCIELabClipL() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabClipL - Return the closest L* + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELabClipL (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Return the closest L* for a specific hue and chroma. + * This routine takes any color as input and outputs + * a CIE XYZ color. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor *pColor; + XcmsColor Lab_max; + XcmsFloat hue, chroma, maxChroma; + Status retval; + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor) { + /* + * GRAY ! + */ + return(XcmsFailure); + } else { + /* Convert from CIEXYZ to CIE L*u*v* format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + hue = XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star); + chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star); + /* Step 1: compute the maximum L* and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&Lab_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsCIELabQueryMaxLCRGB (&myCCC, hue, &Lab_max, + (XcmsRGBi *)NULL) == XcmsFailure) { + return (XcmsFailure); + } + maxChroma = XCMS_CIELAB_PMETRIC_CHROMA(Lab_max.spec.CIELab.a_star, + Lab_max.spec.CIELab.b_star); + + /* Now check and return the appropriate L* */ + if (chroma == maxChroma) { + /* When the chroma input is equal to the maximum chroma */ + /* merely return the L* for that chroma. */ + memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor)); + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else if (chroma > maxChroma) { + /* When the chroma input is greater than the maximum chroma */ + /* merely return the L* and chroma for the given hue. */ + memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor)); + return (XcmsFailure); + } else if (pColor->spec.CIELab.L_star < Lab_max.spec.CIELab.L_star) { + /* Find the minimum lightness for the given chroma. */ + if (pColor->format != XcmsCIELabFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELabQueryMinL(&myCCC, degrees(hue), chroma, pColor) + == XcmsFailure) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else { + /* Find the maximum lightness for the given chroma. */ + if (pColor->format != XcmsCIELabFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELabQueryMaxL(&myCCC, degrees(hue), chroma, pColor) + == XcmsFailure) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/LabGcLC.c b/src/xcms/LabGcLC.c new file mode 100644 index 0000000..8ffaf8c --- /dev/null +++ b/src/xcms/LabGcLC.c @@ -0,0 +1,225 @@ +/* $Xorg: LabGcLC.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELabGcLC.c + * + * DESCRIPTION + * Source for XcmsCIELabClipLab() gamut + * compression function. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * INTERNALS + * Internal defines that need NOT be exported to any package or + * program using this package. + */ +#define MAXBISECTCOUNT 100 + +/* + * EXTERNS + */ +extern Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabClipLab - Return the closest L* and chroma + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELabClipLab (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * This routine will find the closest L* and chroma + * for a specific hue. The color input is converted to + * CIE L*u*v* format and returned as CIE XYZ format. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsCCCRec myCCC; + XcmsColor *pColor; + XcmsColor Lab_max; + XcmsFloat hue, chroma, maxChroma; + XcmsFloat Chroma, bestChroma, Lstar, maxLstar, saveLstar; + XcmsFloat bestLstar, bestastar, bestbstar; + XcmsFloat nT, saveDist, tmpDist; + XcmsRGBi rgb_max; + int nCount, nMaxCount, nI, nILast; + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* inherit screen white */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression func */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIELabFormat); + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } + + /* Convert from CIEXYZ to CIELab format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + /* Step 1: compute the maximum L* and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + saveLstar = pColor->spec.CIELab.L_star; + hue = XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star); + chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star); + memcpy((char *)&Lab_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsCIELabQueryMaxLCRGB (&myCCC, hue, &Lab_max, &rgb_max) + == XcmsFailure) { + return (XcmsFailure); + } + maxLstar = Lab_max.spec.CIELab.L_star; + + /* Now check and return the appropriate L* */ + if (saveLstar == maxLstar) { + /* When the L* input is equal to the maximum L* */ + /* merely return the maximum Lab point. */ + memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor)); + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else { + /* return the closest point on the hue leaf. */ + /* must do a bisection here to compute the delta e. */ + maxChroma = XCMS_CIELAB_PMETRIC_CHROMA(Lab_max.spec.CIELab.a_star, + Lab_max.spec.CIELab.b_star); + nMaxCount = MAXBISECTCOUNT; + nI = nMaxCount / 2; + bestLstar = Lstar = pColor->spec.CIELab.L_star; + bestastar = pColor->spec.CIELab.a_star; + bestbstar = pColor->spec.CIELab.b_star; + bestChroma = Chroma = chroma; + saveDist = XCMS_SQRT(((Chroma - maxChroma) * (Chroma - maxChroma)) + + ((Lstar - maxLstar) * (Lstar - maxLstar))); + for (nCount = 0; nCount < nMaxCount; nCount++) { + nT = (XcmsFloat) nI / (XcmsFloat) nMaxCount; + if (saveLstar > maxLstar) { + pColor->spec.RGBi.red = rgb_max.red * (1.0 - nT) + nT; + pColor->spec.RGBi.green = rgb_max.green * (1.0 - nT) + nT; + pColor->spec.RGBi.blue = rgb_max.blue * (1.0 - nT) + nT; + } else { + pColor->spec.RGBi.red = rgb_max.red - (rgb_max.red * nT); + pColor->spec.RGBi.green = rgb_max.green - (rgb_max.green * nT); + pColor->spec.RGBi.blue = rgb_max.blue - (rgb_max.blue * nT); + } + pColor->format = XcmsRGBiFormat; + + /* Convert from RGBi to CIE Lab */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat, + (Bool *) NULL) == XcmsFailure) { + return (XcmsFailure); + } + chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star, + pColor->spec.CIELab.b_star); + tmpDist = XCMS_SQRT(((Chroma - chroma) * (Chroma - chroma)) + + ((Lstar - pColor->spec.CIELab.L_star) * + (Lstar - pColor->spec.CIELab.L_star))); + nILast = nI; + if (tmpDist > saveDist) { + nI /= 2; + } else { + nI = (nMaxCount + nI) / 2; + saveDist = tmpDist; + bestLstar = pColor->spec.CIELab.L_star; + bestastar = pColor->spec.CIELab.a_star; + bestbstar = pColor->spec.CIELab.b_star; + bestChroma = chroma; + } + if (nI == nILast || nI == 0) { + break; + } + } + if (bestChroma >= maxChroma) { + pColor->spec.CIELab.L_star = maxLstar; + pColor->spec.CIELab.a_star = Lab_max.spec.CIELab.a_star; + pColor->spec.CIELab.b_star = Lab_max.spec.CIELab.b_star; + } else { + pColor->spec.CIELab.L_star = bestLstar; + pColor->spec.CIELab.a_star = bestastar; + pColor->spec.CIELab.b_star = bestbstar; + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + } + return(retval); +} diff --git a/src/xcms/LabMnL.c b/src/xcms/LabMnL.c new file mode 100644 index 0000000..c5ca3e8 --- /dev/null +++ b/src/xcms/LabMnL.c @@ -0,0 +1,218 @@ +/* $Xorg: LabMnL.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELabMnL.c + * + * DESCRIPTION + * Source for the XcmsCIELabQueryMinL() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_L_STAR (XcmsFloat)40.0 + +/* + * EXTERNS + */ +extern Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabQueryMinL - Compute max Lstar for a hue and chroma + * + * SYNOPSIS + */ +Status +XcmsCIELabQueryMinL(ccc, hue_angle, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsFloat chroma; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum Lstar for a specified hue_angle and chroma. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor max_lc, tmp, prev; + XcmsFloat max_chroma, tmp_chroma; + XcmsFloat hue, nT, nChroma, lastChroma, prevChroma; + XcmsFloat rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELab.L_star = START_L_STAR; + tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, chroma); + tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, chroma); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELabFormat; + + /* Step 1: Obtain the maximum L_star and chroma for this hue. */ + if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + max_chroma = XCMS_CIELAB_PMETRIC_CHROMA(max_lc.spec.CIELab.a_star, + max_lc.spec.CIELab.b_star); + + if (max_chroma <= chroma) { + /* + * If the chroma is greater than the chroma for the + * maximum L/chroma point then the L_star is the + * the L_star for the maximum L_star/chroma point. + * This is an error but I return the best approximation I can. + * Thus the inconsistency. + */ + memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + return(XcmsSuccess); + } + + /* + * If the chroma is equal to the chroma for the + * maximum L_star/chroma point then the L_star is the + * the L_star for the maximum L* and chroma point. + */ + /* if (max_chroma == chroma) { + * memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + * return(XcmsSuccess); + * } + */ + + /* must do a bisection here to compute the maximum L* */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nChroma = chroma; + tmp_chroma = max_chroma; + lastChroma = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevChroma = lastChroma; + lastChroma = tmp_chroma; + nT = (nChroma - max_chroma) / max_chroma * rFactor; + memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor)); + tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT); + tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT); + tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT); + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELab */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + tmp_chroma = XCMS_CIELAB_PMETRIC_CHROMA(tmp.spec.CIELab.a_star, + tmp.spec.CIELab.b_star); + if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) { + /* Found It! */ + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } + nChroma += chroma - tmp_chroma; + if (nChroma > max_chroma) { + nChroma = max_chroma; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nChroma < 0.0) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + return(XcmsSuccess); + } else if (tmp_chroma <= prevChroma + EPS && + tmp_chroma >= prevChroma - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + + if (nCount >= nMaxCount) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + } + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LabMxC.c b/src/xcms/LabMxC.c new file mode 100644 index 0000000..a1a3d69 --- /dev/null +++ b/src/xcms/LabMxC.c @@ -0,0 +1,205 @@ +/* $Xorg: LabMxC.c,v 1.3 2000/08/17 19:44:40 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * CIELabMxC.c + * + * DESCRIPTION + * Source for the XcmsCIELabQueryMaxC() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_CHROMA (XcmsFloat)3.6 +#define TOPL (XcmsFloat)100.0 + +/* + * EXTERNS + */ +extern Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabQueryMaxC - max chroma for a hue_angle and L_star + * + * SYNOPSIS + */ +Status +XcmsCIELabQueryMaxC(ccc, hue_angle, L_star, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsFloat L_star; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum chroma for a specific hue_angle and L_star. + * The returned format is in XcmsCIELabFormat. + * + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor tmp; + XcmsColor max_lc; + XcmsFloat n_L_star, last_L_star, prev_L_star; + XcmsFloat hue, lastaStar, lastbStar, /*lastChroma,*/ maxDist, nT, rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* Use my own CCC and inherit screen white Pt */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut comp func */ + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELab.L_star = L_star; + tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, START_CHROMA); + tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, START_CHROMA); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELabFormat; + + /* Step 1: compute the maximum L_star and chroma for this hue. */ + memcpy((char *)&max_lc, (char *)&tmp, sizeof(XcmsColor)); + if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Step 2: Do a bisection here to compute the maximum chroma + * Note the differences between when the point to be found + * is above the maximum LC point and when it is below. + */ + if (L_star <= max_lc.spec.CIELab.L_star) { + maxDist = max_lc.spec.CIELab.L_star; + } else { + maxDist = TOPL - max_lc.spec.CIELab.L_star; + } + + n_L_star = L_star; + last_L_star = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prev_L_star = last_L_star; + last_L_star = tmp.spec.CIELab.L_star; +/* lastChroma = XCMS_CIELAB_PMETRIC_CHROMA(tmp.spec.CIELab.a_star, */ +/* tmp.spec.CIELab.b_star); */ + lastaStar = tmp.spec.CIELab.a_star; + lastbStar = tmp.spec.CIELab.b_star; + nT = (n_L_star - max_lc.spec.CIELab.L_star) / maxDist * rFactor; + if (nT > 0) { + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + } else { + tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT); + tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT); + tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT); + } + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELab */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Now check if we've reached the target L_star + */ + /* printf("result Lstar = %lf\n", tmp.spec.CIELab.L_star); */ + if (tmp.spec.CIELab.L_star <= L_star + EPS && + tmp.spec.CIELab.L_star >= L_star - EPS) { + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); + } + if (nT > 0) { + n_L_star += ((TOPL - n_L_star) * + (L_star - tmp.spec.CIELab.L_star)) / (TOPL - L_star); + } else { + n_L_star *= L_star / tmp.spec.CIELuv.L_star; + } + if (tmp.spec.CIELab.L_star <= prev_L_star + EPS && + tmp.spec.CIELab.L_star >= prev_L_star - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + /* printf("rFactor = %lf\n", rFactor); */ + } + } + if (XCMS_FABS(last_L_star - L_star) < + XCMS_FABS(tmp.spec.CIELab.L_star - L_star)) { + tmp.spec.CIELab.a_star = lastaStar; + tmp.spec.CIELab.b_star = lastbStar; +/* tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, lastChroma); */ +/* tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, lastChroma); */ + } + tmp.spec.CIELab.L_star = L_star; + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LabMxL.c b/src/xcms/LabMxL.c new file mode 100644 index 0000000..a31a8f4 --- /dev/null +++ b/src/xcms/LabMxL.c @@ -0,0 +1,218 @@ +/* $Xorg: LabMxL.c,v 1.3 2000/08/17 19:44:40 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELabMxL.c + * + * DESCRIPTION + * Source for the XcmsCIELabQueryMaxL() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_L_STAR (XcmsFloat)40 + +/* + * EXTERNS + */ +extern Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabQueryMaxL - Compute max Lstar for a hue and chroma + * + * SYNOPSIS + */ +Status +XcmsCIELabQueryMaxL(ccc, hue_angle, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue in degrees */ + XcmsFloat chroma; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum Lstar for a specified hue_angle and chroma. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor max_lc, tmp, prev; + XcmsFloat max_chroma, tmp_chroma; + XcmsFloat hue, nT, nChroma, lastChroma, prevChroma; + XcmsFloat rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELab.L_star = START_L_STAR; + tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, chroma); + tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, chroma); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELabFormat; + + /* Step 1: Obtain the maximum L_star and chroma for this hue. */ + if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + max_chroma = XCMS_CIELAB_PMETRIC_CHROMA(max_lc.spec.CIELab.a_star, + max_lc.spec.CIELab.b_star); + + if (max_chroma <= chroma) { + /* + * If the chroma is greater than the chroma for the + * maximum L/chroma point then the L_star is the + * the L_star for the maximum L_star/chroma point. + * This is an error but I return the best approximation I can. + * Thus the inconsistency. + */ + memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + return(XcmsSuccess); + } + + /* + * If the chroma is equal to the chroma for the + * maximum L_star/chroma point then the L_star is the + * the L_star for the maximum L* and chroma point. + */ + /* if (max_chroma == chroma) { + * memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + * return(XcmsSuccess); + * } + */ + + /* must do a bisection here to compute the maximum L* */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nChroma = chroma; + tmp_chroma = max_chroma; + lastChroma = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevChroma = lastChroma; + lastChroma = tmp_chroma; + nT = (1.0 - (nChroma / max_chroma)) * rFactor; + memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor)); + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELab */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + tmp_chroma = XCMS_CIELAB_PMETRIC_CHROMA(tmp.spec.CIELab.a_star, + tmp.spec.CIELab.b_star); + if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) { + /* Found It! */ + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } + nChroma += chroma - tmp_chroma; + if (nChroma > max_chroma) { + nChroma = max_chroma; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nChroma < 0.0) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + return(XcmsSuccess); + } else if (tmp_chroma <= prevChroma + EPS && + tmp_chroma >= prevChroma - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + + if (nCount >= nMaxCount) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + } + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LabMxLC.c b/src/xcms/LabMxLC.c new file mode 100644 index 0000000..6fdeeb1 --- /dev/null +++ b/src/xcms/LabMxLC.c @@ -0,0 +1,226 @@ +/* $Xorg: LabMxLC.c,v 1.3 2000/08/17 19:44:40 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * CIELabMxVC.c + * + * DESCRIPTION + * Source for the XcmsCIELabQueryMaxLC() gamut boundary + * querying routine. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + * and + * Fred W. Billmeyer & Max Saltzman, "Principles of Color + * Technology", John Wily & Sons, Inc, 1981. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) +#define START_LSTAR (XcmsFloat)40.0 +#define START_CHROMA (XcmsFloat)3.6 + +/* + * EXTERNS + */ +extern Status _XcmsConvertColorsWithWhitePt(); + +/* + * FORWARD DECLARATIONS + */ +Status _XcmsCIELabQueryMaxLCRGB(); + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsCIELabQueryMaxLCRGB - Compute maximum L* and chroma. + * + * SYNOPSIS + */ +Status +_XcmsCIELabQueryMaxLCRGB(ccc, hue, pColor_return, pRGB_return) + XcmsCCC ccc; + XcmsFloat hue; /* hue in radians */ + XcmsColor *pColor_return; + XcmsRGBi *pRGB_return; + +/* + * DESCRIPTION + * Return the maximum psychometric chroma for a specified + * hue, and the corresponding L*. This is computed + * by a binary search of all possible chromas. An assumption + * is made that there are no local maxima. Use the unrounded + * Max psychometric chroma because the difference check can be + * small. + * + * NOTE: No local CCC is used because this is a private + * routine and all routines that call it are expected + * to behave properly, i.e. send a local CCC with + * no white adjust function and no gamut compression + * function. + * + * This routine only accepts hue in radians as input and outputs + * Lab and RGBi. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsFloat nSmall, nLarge; + XcmsColor tmp; + + tmp.format = XcmsCIELabFormat; + /* Use some unreachable color on the given hue */ + tmp.spec.CIELab.L_star = START_LSTAR; + tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, START_CHROMA); + tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, START_CHROMA); + /* + * Convert from Lab to RGB + * + * Note that the CIEXYZ to RGBi conversion routine must stuff the + * out of bounds RGBi values in tmp when the ccc->gamutCompProc + * is NULL. + */ + if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, ScreenWhitePointOfCCC(ccc), + (unsigned int)1, XcmsRGBiFormat, (Bool *) NULL) + == XcmsFailure) && tmp.format != XcmsRGBiFormat) { + return (XcmsFailure); + } + + /* Now pick the smallest RGB */ + nSmall = MIN3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Make the smallest RGB equal to zero */ + tmp.spec.RGBi.red -= nSmall; + tmp.spec.RGBi.green -= nSmall; + tmp.spec.RGBi.blue -= nSmall; + + /* Now pick the largest RGB */ + nLarge = MAX3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Scale the RGB values based on the largest one */ + tmp.spec.RGBi.red /= nLarge; + tmp.spec.RGBi.green /= nLarge; + tmp.spec.RGBi.blue /= nLarge; + tmp.format = XcmsRGBiFormat; + + /* If the calling routine wants RGB value give them the ones used. */ + if (pRGB_return) { + pRGB_return->red = tmp.spec.RGBi.red; + pRGB_return->green = tmp.spec.RGBi.green; + pRGB_return->blue = tmp.spec.RGBi.blue; + } + + /* Convert from RGBi to Lab */ + if (_XcmsConvertColorsWithWhitePt(ccc, &tmp, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat, (Bool *) NULL) + == XcmsFailure) { + return (XcmsFailure); + } + + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return (XcmsSuccess); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabQueryMaxLC - Compute maximum L* and chroma. + * + * SYNOPSIS + */ +Status +XcmsCIELabQueryMaxLC (ccc, hue_angle, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue_angle in degrees */ + XcmsColor *pColor_return; + +/* + * DESCRIPTION + * Return the point of maximum chroma for the specified + * hue_angle. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc)NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + return(_XcmsCIELabQueryMaxLCRGB (&myCCC, radians(hue_angle), pColor_return, + (XcmsRGBi *)NULL)); +} diff --git a/src/xcms/LabWpAj.c b/src/xcms/LabWpAj.c new file mode 100644 index 0000000..b4fc4a3 --- /dev/null +++ b/src/xcms/LabWpAj.c @@ -0,0 +1,97 @@ +/* $Xorg: LabWpAj.c,v 1.3 2000/08/17 19:44:40 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * CIELabWpAj.c + * + * DESCRIPTION + * This file contains routine(s) that support white point + * adjustment of color specifications in the CIE L*a*b* color + * space. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ + +extern Status _XcmsConvertColorsWithWhitePt(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELabWhiteShiftColors + * + * SYNOPSIS + */ +Status +XcmsCIELabWhiteShiftColors(ccc, pWhitePtFrom, pWhitePtTo, destSpecFmt, + pColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pWhitePtFrom; + XcmsColor *pWhitePtTo; + XcmsColorFormat destSpecFmt; + XcmsColor *pColors_in_out; + unsigned int nColors; + Bool *pCompressed; +/* + * DESCRIPTION + * Adjust color specifications in XcmsColor structures for + * differences in white points. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression, + * XcmsSuccessWithCompression if succeeded with gamut + * compression. + */ +{ + if (pWhitePtFrom == NULL || pWhitePtTo == NULL || pColors_in_out == NULL) { + return(0); + } + + /* + * Convert to CIELab using pWhitePtFrom + */ + if (_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePtFrom, + nColors, XcmsCIELabFormat, pCompressed) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Convert from CIELab to destSpecFmt using pWhitePtTo + */ + return(_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, + pWhitePtTo, nColors, destSpecFmt, pCompressed)); +} diff --git a/src/xcms/Luv.c b/src/xcms/Luv.c new file mode 100644 index 0000000..9cb56cf --- /dev/null +++ b/src/xcms/Luv.c @@ -0,0 +1,385 @@ +/* $Xorg: Luv.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * CIELuv.c + * + * DESCRIPTION + * This file contains routines that support the CIE L*u*v* + * color space to include conversions to and from the CIE + * XYZ space. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + * and + * Fred W. Billmeyer & Max Saltzman, "Principles of Color + * Technology", John Wily & Sons, Inc, 1981. + */ + +#include <X11/Xos.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ + +extern char _XcmsCIELuv_prefix[]; + + +/* + * FORWARD DECLARATIONS + */ + +static int CIELuv_ParseString(); +static Status XcmsCIELuv_ValidSpec(); + +/* + * DEFINES + * Internal definitions that need NOT be exported to any package + * or program using this package. + */ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif + + +/* + * LOCAL VARIABLES + */ + + /* + * NULL terminated list of functions applied to get from CIELuv to CIEXYZ + */ +static XcmsConversionProc Fl_CIELuv_to_CIEXYZ[] = { + XcmsCIELuvToCIEuvY, + XcmsCIEuvYToCIEXYZ, + NULL +}; + + /* + * NULL terminated list of functions applied to get from CIEXYZ to CIELuv + */ +static XcmsConversionProc Fl_CIEXYZ_to_CIELuv[] = { + XcmsCIEXYZToCIEuvY, + XcmsCIEuvYToCIELuv, + NULL +}; + +/* + * GLOBALS + */ + + /* + * CIE Luv Color Space + */ +XcmsColorSpace XcmsCIELuvColorSpace = + { + _XcmsCIELuv_prefix, /* prefix */ + XcmsCIELuvFormat, /* id */ + CIELuv_ParseString, /* parseString */ + Fl_CIELuv_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_CIELuv, /* from_CIEXYZ */ + 1 + }; + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIELuv_ParseString + * + * SYNOPSIS + */ +static int +CIELuv_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsCIELuvFormat. + * The assumed CIELuv string syntax is: + * CIELuv:<L>/<u>/<v> + * Where L, u, and v are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsCIELuv_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.CIELuv.L_star, + &pColor->spec.CIELuv.u_star, + &pColor->spec.CIELuv.v_star) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsCIELuvFormat; + pColor->pixel = 0; + return(XcmsCIELuv_ValidSpec(pColor)); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuv_ValidSpec + * + * SYNOPSIS + */ +static Status +XcmsCIELuv_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if color specification valid for CIE L*u*v*. + * + * RETURNS + * XcmsFailure if invalid, + * XcmsSuccess if valid. + * + */ +{ + if (pColor->format != XcmsCIELuvFormat + || + (pColor->spec.CIELuv.L_star < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIELuv.L_star > 100.0 + XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIELuvToCIEuvY - convert CIELuv to CIEuvY + * + * SYNOPSIS + */ +Status +XcmsCIELuvToCIEuvY(ccc, pLuv_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pLuv_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIELuv format to CIEuvY format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsColor *pColor = pColors_in_out; + XcmsColor whitePt; + XcmsCIEuvY uvY_return; + XcmsFloat tmpVal; + register int i; + + /* + * Check arguments + */ + if (pLuv_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEuvY form + */ + if (pLuv_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pLuv_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, + 1, XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + pLuv_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (pLuv_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is CIELuv and is valid */ + if (!XcmsCIELuv_ValidSpec(pColor)) { + return(XcmsFailure); + } + + if (pColor->spec.CIELuv.L_star < 7.99953624) { + uvY_return.Y = pColor->spec.CIELuv.L_star / 903.29; + } else { + tmpVal = (pColor->spec.CIELuv.L_star + 16.0) / 116.0; + uvY_return.Y = tmpVal * tmpVal * tmpVal; /* tmpVal ** 3 */ + } + + + + if (pColor->spec.CIELuv.L_star == 0.0) { + uvY_return.u_prime = pLuv_WhitePt->spec.CIEuvY.u_prime; + uvY_return.v_prime = pLuv_WhitePt->spec.CIEuvY.v_prime; + } else { + tmpVal = 13.0 * (pColor->spec.CIELuv.L_star / 100.0); + uvY_return.u_prime = pColor->spec.CIELuv.u_star/tmpVal + + pLuv_WhitePt->spec.CIEuvY.u_prime; + uvY_return.v_prime = pColor->spec.CIELuv.v_star/tmpVal + + pLuv_WhitePt->spec.CIEuvY.v_prime; + } + /* Copy result to pColor */ + memcpy((char *)&pColor->spec, (char *)&uvY_return, sizeof(XcmsCIEuvY)); + + /* Identify that the format is now CIEuvY */ + pColor->format = XcmsCIEuvYFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEuvYToCIELuv - convert CIEuvY to CIELuv + * + * SYNOPSIS + */ +Status +XcmsCIEuvYToCIELuv(ccc, pLuv_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pLuv_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIEuvY format to CIELab format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsColor *pColor = pColors_in_out; + XcmsColor whitePt; + XcmsCIELuv Luv_return; + XcmsFloat tmpVal; + register int i; + + /* + * Check arguments + */ + if (pLuv_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Make sure white point is in CIEuvY form + */ + if (pLuv_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pLuv_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, + (XcmsColor *)NULL, 1, XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + pLuv_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (pLuv_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + if (!_XcmsCIEuvY_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* Now convert the uvY to Luv */ + Luv_return.L_star = + (pColor->spec.CIEuvY.Y < 0.008856) + ? + (pColor->spec.CIEuvY.Y * 903.29) + : + ((XcmsFloat)(XCMS_CUBEROOT(pColor->spec.CIEuvY.Y) * 116.0) - 16.0); + tmpVal = 13.0 * (Luv_return.L_star / 100.0); + Luv_return.u_star = tmpVal * + (pColor->spec.CIEuvY.u_prime - pLuv_WhitePt->spec.CIEuvY.u_prime); + Luv_return.v_star = tmpVal * + (pColor->spec.CIEuvY.v_prime - pLuv_WhitePt->spec.CIEuvY.v_prime); + + /* Copy result to pColor */ + memcpy((char *)&pColor->spec, (char *)&Luv_return, sizeof(XcmsCIELuv)); + + /* Identify that the format is now CIEuvY */ + pColor->format = XcmsCIELuvFormat; + } + return(XcmsSuccess); +} diff --git a/src/xcms/LuvGcC.c b/src/xcms/LuvGcC.c new file mode 100644 index 0000000..fa3b3f1 --- /dev/null +++ b/src/xcms/LuvGcC.c @@ -0,0 +1,124 @@ +/* $Xorg: LuvGcC.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELuvGcC.c + * + * DESCRIPTION + * Source for XcmsCIELuvClipuv() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvClipuv - Reduce the chroma for a hue and L* + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELuvClipuv (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Reduce the Chroma for a specific hue and chroma to + * to bring the given color into the gamut of the + * specified device. As required of gamut compression + * functions, this routine returns pColor_in_out + * in XcmsCIEXYZFormat on successful completion. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsColor *pColor; + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < PseudoColor) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIELuvFormat); + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } else { + if (pColor->format != XcmsCIELuvFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIELuvFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELuvQueryMaxC(ccc, + degrees(XCMS_CIELUV_PMETRIC_HUE(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star)), + pColor->spec.CIELuv.L_star, + pColor) == XcmsFailure) { + return(XcmsFailure); + } + retval = _XcmsDIConvertColors(ccc, pColor, + &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat); + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/LuvGcL.c b/src/xcms/LuvGcL.c new file mode 100644 index 0000000..32d09bd --- /dev/null +++ b/src/xcms/LuvGcL.c @@ -0,0 +1,176 @@ +/* $Xorg: LuvGcL.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELuvGcL.c + * + * DESCRIPTION + * Source for XcmsCIELuvClipL() gamut compression routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvClipL - Return the closest L* + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELuvClipL (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * Return the closest L* for a specific hue and chroma. + * This routine takes any color as input and outputs + * a CIE XYZ color. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor *pColor; + XcmsColor Luv_max; + XcmsFloat hue, chroma, maxChroma; + Status retval; + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor) { + /* + * GRAY ! + */ + return(XcmsFailure); + } else { + /* Convert from CIEXYZ to CIE L*u*v* format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + hue = XCMS_CIELUV_PMETRIC_HUE(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star); + chroma = XCMS_CIELUV_PMETRIC_CHROMA(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star); + /* Step 1: compute the maximum L* and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + memcpy((char *)&Luv_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsCIELuvQueryMaxLCRGB (&myCCC, hue, &Luv_max, + (XcmsRGBi *)NULL) == XcmsFailure) { + return (XcmsFailure); + } + maxChroma = XCMS_CIELUV_PMETRIC_CHROMA(Luv_max.spec.CIELuv.u_star, + Luv_max.spec.CIELuv.v_star); + + /* Now check and return the appropriate L* */ + if (chroma == maxChroma) { + /* When the chroma input is equal to the maximum chroma */ + /* merely return the L* for that chroma. */ + memcpy((char *)pColor, (char *)&Luv_max, sizeof(XcmsColor)); + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else if (chroma > maxChroma) { + /* When the chroma input is greater than the maximum chroma */ + /* merely return the L* and chroma for the given hue. */ + memcpy((char *)pColor, (char *)&Luv_max, sizeof(XcmsColor)); + return (XcmsFailure); + } else if (pColor->spec.CIELuv.L_star < Luv_max.spec.CIELuv.L_star) { + /* Find the minimum lightness for the given chroma. */ + if (pColor->format != XcmsCIELuvFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELuvQueryMinL(&myCCC, degrees(hue), chroma, pColor) + == XcmsFailure) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else { + /* Find the maximum lightness for the given chroma. */ + if (pColor->format != XcmsCIELuvFormat) { + if (_XcmsDIConvertColors(ccc, pColor, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat) + == XcmsFailure) { + return(XcmsFailure); + } + } + if (XcmsCIELuvQueryMaxL(&myCCC, degrees(hue), chroma, pColor) + == XcmsFailure) { + return (XcmsFailure); + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + return(retval); + } +} diff --git a/src/xcms/LuvGcLC.c b/src/xcms/LuvGcLC.c new file mode 100644 index 0000000..376f5f4 --- /dev/null +++ b/src/xcms/LuvGcLC.c @@ -0,0 +1,225 @@ +/* $Xorg: LuvGcLC.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELuvGcLC.c + * + * DESCRIPTION + * Source for XcmsCIELuvClipLuv() gamut + * compression function. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * INTERNALS + * Internal defines that need NOT be exported to any package or + * program using this package. + */ +#define MAXBISECTCOUNT 100 + +/* + * EXTERNS + */ +extern Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvClipLuv - Return the closest L* and chroma + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIELuvClipLuv (ccc, pColors_in_out, nColors, i, pCompressed) + XcmsCCC ccc; + XcmsColor *pColors_in_out; + unsigned int nColors; + unsigned int i; + Bool *pCompressed; +/* + * DESCRIPTION + * This routine will find the closest L* and chroma + * for a specific hue. The color input is converted to + * CIE L*u*v* format and returned as CIE XYZ format. + * + * Since this routine works with the L* within + * pColor_in_out intermediate results may be returned + * even though it may be invalid. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + Status retval; + XcmsCCCRec myCCC; + XcmsColor *pColor; + XcmsColor Luv_max; + XcmsFloat hue, chroma, maxChroma; + XcmsFloat Chroma, bestChroma, Lstar, maxLstar, saveLstar; + XcmsFloat bestLstar, bestustar, bestvstar; + XcmsFloat nT, saveDist, tmpDist; + XcmsRGBi rgb_max; + int nCount, nMaxCount, nI, nILast; + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* inherit screen white */ + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression func */ + + /* + * Color specification passed as input can be assumed to: + * 1. Be in XcmsCIEXYZFormat + * 2. Already be white point adjusted for the Screen White Point. + * This means that the white point now associated with this + * color spec is the Screen White Point (even if the + * ccc->clientWhitePt differs). + */ + + pColor = pColors_in_out + i; + + if (ccc->visual->class < StaticColor) { + /* + * GRAY ! + */ + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIELuvFormat); + _XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc), + 1, XcmsCIEXYZFormat); + if (pCompressed) { + *(pCompressed + i) = True; + } + return(XcmsSuccess); + } + + /* Convert from CIEXYZ to CIELuv format */ + if (_XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat) + == XcmsFailure) { + return(XcmsFailure); + } + + /* Step 1: compute the maximum L* and chroma for this hue. */ + /* This copy may be overkill but it preserves the pixel etc. */ + saveLstar = pColor->spec.CIELuv.L_star; + hue = XCMS_CIELUV_PMETRIC_HUE(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star); + chroma = XCMS_CIELUV_PMETRIC_CHROMA(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star); + memcpy((char *)&Luv_max, (char *)pColor, sizeof(XcmsColor)); + if (_XcmsCIELuvQueryMaxLCRGB (&myCCC, hue, &Luv_max, &rgb_max) + == XcmsFailure) { + return (XcmsFailure); + } + maxLstar = Luv_max.spec.CIELuv.L_star; + + /* Now check and return the appropriate L* */ + if (saveLstar == maxLstar) { + /* When the L* input is equal to the maximum L* */ + /* merely return the maximum Luv point. */ + memcpy((char *)pColor, (char *)&Luv_max, sizeof(XcmsColor)); + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + } else { + /* return the closest point on the hue leaf. */ + /* must do a bisection here to compute the delta e. */ + maxChroma = XCMS_CIELUV_PMETRIC_CHROMA(Luv_max.spec.CIELuv.u_star, + Luv_max.spec.CIELuv.v_star); + nMaxCount = MAXBISECTCOUNT; + nI = nMaxCount / 2; + bestLstar = Lstar = pColor->spec.CIELuv.L_star; + bestustar = pColor->spec.CIELuv.u_star; + bestvstar = pColor->spec.CIELuv.v_star; + bestChroma = Chroma = chroma; + saveDist = XCMS_SQRT(((Chroma - maxChroma) * (Chroma - maxChroma)) + + ((Lstar - maxLstar) * (Lstar - maxLstar))); + for (nCount = 0; nCount < nMaxCount; nCount++) { + nT = (XcmsFloat) nI / (XcmsFloat) nMaxCount; + if (saveLstar > maxLstar) { + pColor->spec.RGBi.red = rgb_max.red * (1.0 - nT) + nT; + pColor->spec.RGBi.green = rgb_max.green * (1.0 - nT) + nT; + pColor->spec.RGBi.blue = rgb_max.blue * (1.0 - nT) + nT; + } else { + pColor->spec.RGBi.red = rgb_max.red - (rgb_max.red * nT); + pColor->spec.RGBi.green = rgb_max.green - (rgb_max.green * nT); + pColor->spec.RGBi.blue = rgb_max.blue - (rgb_max.blue * nT); + } + pColor->format = XcmsRGBiFormat; + + /* Convert from RGBi to CIE Luv */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat, + (Bool *) NULL) == XcmsFailure) { + return (XcmsFailure); + } + chroma = XCMS_CIELUV_PMETRIC_CHROMA(pColor->spec.CIELuv.u_star, + pColor->spec.CIELuv.v_star); + tmpDist = XCMS_SQRT(((Chroma - chroma) * (Chroma - chroma)) + + ((Lstar - pColor->spec.CIELuv.L_star) * + (Lstar - pColor->spec.CIELuv.L_star))); + nILast = nI; + if (tmpDist > saveDist) { + nI /= 2; + } else { + nI = (nMaxCount + nI) / 2; + saveDist = tmpDist; + bestLstar = pColor->spec.CIELuv.L_star; + bestustar = pColor->spec.CIELuv.u_star; + bestvstar = pColor->spec.CIELuv.v_star; + bestChroma = chroma; + } + if (nI == nILast || nI == 0) { + break; + } + } + if (bestChroma >= maxChroma) { + pColor->spec.CIELuv.L_star = maxLstar; + pColor->spec.CIELuv.u_star = Luv_max.spec.CIELuv.u_star; + pColor->spec.CIELuv.v_star = Luv_max.spec.CIELuv.v_star; + } else { + pColor->spec.CIELuv.L_star = bestLstar; + pColor->spec.CIELuv.u_star = bestustar; + pColor->spec.CIELuv.v_star = bestvstar; + } + retval = _XcmsDIConvertColors(&myCCC, pColor, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat); + + if (retval != XcmsFailure && pCompressed != NULL) { + *(pCompressed + i) = True; + } + } + return(retval); +} diff --git a/src/xcms/LuvMnL.c b/src/xcms/LuvMnL.c new file mode 100644 index 0000000..c687037 --- /dev/null +++ b/src/xcms/LuvMnL.c @@ -0,0 +1,218 @@ +/* $Xorg: LuvMnL.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELuvMnL.c + * + * DESCRIPTION + * Source for the XcmsCIELuvQueryMinL() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_L_STAR (XcmsFloat)40.0 + +/* + * EXTERNS + */ +extern Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvQueryMinL - Compute max Lstar for a hue and chroma + * + * SYNOPSIS + */ +Status +XcmsCIELuvQueryMinL(ccc, hue_angle, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsFloat chroma; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum Lstar for a specified hue_angle and chroma. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor max_lc, tmp, prev; + XcmsFloat max_chroma, tmp_chroma; + XcmsFloat hue, nT, nChroma, lastChroma, prevChroma; + XcmsFloat rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELuv.L_star = START_L_STAR; + tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, chroma); + tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, chroma); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELuvFormat; + + /* Step 1: Obtain the maximum L_star and chroma for this hue. */ + if (_XcmsCIELuvQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + max_chroma = XCMS_CIELUV_PMETRIC_CHROMA(max_lc.spec.CIELuv.u_star, + max_lc.spec.CIELuv.v_star); + + if (max_chroma <= chroma) { + /* + * If the chroma is greater than the chroma for the + * maximum L/chroma point then the L_star is the + * the L_star for the maximum L_star/chroma point. + * This is an error but I return the best approximation I can. + * Thus the inconsistency. + */ + memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + return(XcmsSuccess); + } + + /* + * If the chroma is equal to the chroma for the + * maximum L_star/chroma point then the L_star is the + * the L_star for the maximum L* and chroma point. + */ + /* if (max_chroma == chroma) { + * memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + * return(XcmsSuccess); + * } + */ + + /* must do a bisection here to compute the maximum L* */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nChroma = chroma; + tmp_chroma = max_chroma; + lastChroma = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevChroma = lastChroma; + lastChroma = tmp_chroma; + nT = (nChroma - max_chroma) / max_chroma * rFactor; + memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor)); + tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT); + tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT); + tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT); + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELuv */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + tmp_chroma = XCMS_CIELUV_PMETRIC_CHROMA(tmp.spec.CIELuv.u_star, + tmp.spec.CIELuv.v_star); + if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) { + /* Found It! */ + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } + nChroma += chroma - tmp_chroma; + if (nChroma > max_chroma) { + nChroma = max_chroma; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nChroma < 0.0) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + return(XcmsSuccess); + } else if (tmp_chroma <= prevChroma + EPS && + tmp_chroma >= prevChroma - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + + if (nCount >= nMaxCount) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + } + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LuvMxC.c b/src/xcms/LuvMxC.c new file mode 100644 index 0000000..100a3b9 --- /dev/null +++ b/src/xcms/LuvMxC.c @@ -0,0 +1,205 @@ +/* $Xorg: LuvMxC.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * CIELuvMxC.c + * + * DESCRIPTION + * Source for the XcmsCIELuvQueryMaxC() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_CHROMA (XcmsFloat)2.2 +#define TOPL (XcmsFloat)100.0 +/* + * EXTERNS + */ +extern Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvQueryMaxC - max chroma for a hue_angle and L_star + * + * SYNOPSIS + */ +Status +XcmsCIELuvQueryMaxC(ccc, hue_angle, L_star, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsFloat L_star; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum chroma for a specific hue_angle and L_star. + * The returned format is in XcmsCIELuvFormat. + * + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor tmp; + XcmsColor max_lc; + XcmsFloat n_L_star, last_L_star, prev_L_star; + XcmsFloat hue, lastuStar, lastvStar, /*lastChroma,*/ maxDist, nT, rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* Use my own CCC and inherit screen white Pt */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut comp func */ + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELuv.L_star = L_star; + tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, START_CHROMA); + tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, START_CHROMA); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELuvFormat; + + /* Step 1: compute the maximum L_star and chroma for this hue. */ + memcpy((char *)&max_lc, (char *)&tmp, sizeof(XcmsColor)); + if (_XcmsCIELuvQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Step 2: Do a bisection here to compute the maximum chroma + * Note the differences between when the point to be found + * is above the maximum LC point and when it is below. + */ + if (L_star <= max_lc.spec.CIELuv.L_star) { + maxDist = max_lc.spec.CIELuv.L_star; + } else { + maxDist = TOPL - max_lc.spec.CIELuv.L_star; + } + + n_L_star = L_star; + last_L_star = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prev_L_star = last_L_star; + last_L_star = tmp.spec.CIELuv.L_star; +/* lastChroma = XCMS_CIELUV_PMETRIC_CHROMA(tmp.spec.CIELuv.u_star, */ +/* tmp.spec.CIELuv.v_star); */ + lastuStar = tmp.spec.CIELuv.u_star; + lastvStar = tmp.spec.CIELuv.v_star; + nT = (n_L_star - max_lc.spec.CIELuv.L_star) / maxDist * rFactor; + /* printf("(n_L_star, nT) = %lf %lf ", n_L_star, nT); */ + if (nT > 0) { + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + } else { + tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT); + tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT); + tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT); + } + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELuv */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Now check if we've reached the target L_star + */ + /* printf("result Lstar = %lf\n", tmp.spec.CIELuv.L_star); */ + if (tmp.spec.CIELuv.L_star <= L_star + EPS && + tmp.spec.CIELuv.L_star >= L_star - EPS) { + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); + } + if (nT > 0) { + n_L_star += ((TOPL - n_L_star) * + (L_star - tmp.spec.CIELuv.L_star)) / (TOPL - L_star); + } else { + n_L_star *= L_star / tmp.spec.CIELuv.L_star; + } + if (tmp.spec.CIELuv.L_star <= prev_L_star + EPS && + tmp.spec.CIELuv.L_star >= prev_L_star - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + /* printf("rFactor = %lf\n", rFactor); */ + } + } + if (XCMS_FABS(last_L_star - L_star) < + XCMS_FABS(tmp.spec.CIELuv.L_star - L_star)) { + tmp.spec.CIELuv.u_star = lastuStar; + tmp.spec.CIELuv.v_star = lastvStar; +/* tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, lastChroma); */ +/* tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, lastChroma); */ + } + tmp.spec.CIELuv.L_star = L_star; + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LuvMxL.c b/src/xcms/LuvMxL.c new file mode 100644 index 0000000..7925b01 --- /dev/null +++ b/src/xcms/LuvMxL.c @@ -0,0 +1,218 @@ +/* $Xorg: LuvMxL.c,v 1.3 2000/08/17 19:44:45 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIELuvMxL.c + * + * DESCRIPTION + * Source for the XcmsCIELuvQueryMaxL() gamut boundary + * querying routine. + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <math.h> + +/* + * DEFINES + */ +#define MAXBISECTCOUNT 100 +#define EPS (XcmsFloat)0.001 +#define START_L_STAR (XcmsFloat)40.0 + +/* + * EXTERNS + */ +extern Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvQueryMaxL - Compute max Lstar for a hue and chroma + * + * SYNOPSIS + */ +Status +XcmsCIELuvQueryMaxL(ccc, hue_angle, chroma, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsFloat chroma; + XcmsColor *pColor_return; +/* + * DESCRIPTION + * Return the maximum Lstar for a specified hue_angle and chroma. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded with no modifications + * + */ +{ + XcmsCCCRec myCCC; + XcmsColor max_lc, tmp, prev; + XcmsFloat max_chroma, tmp_chroma; + XcmsFloat hue, nT, nChroma, lastChroma, prevChroma; + XcmsFloat rFactor; + XcmsRGBi rgb_saved; + int nCount, nMaxCount; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* setup the CCC to use for the conversions. */ + memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc) NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + hue = radians(hue_angle); + tmp.spec.CIELuv.L_star = START_L_STAR; + tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, chroma); + tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, chroma); + tmp.pixel = pColor_return->pixel; + tmp.format = XcmsCIELuvFormat; + + /* Step 1: Obtain the maximum L_star and chroma for this hue. */ + if (_XcmsCIELuvQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved) + == XcmsFailure) { + return(XcmsFailure); + } + + max_chroma = XCMS_CIELUV_PMETRIC_CHROMA(max_lc.spec.CIELuv.u_star, + max_lc.spec.CIELuv.v_star); + + if (max_chroma <= chroma) { + /* + * If the chroma is greater than the chroma for the + * maximum L/chroma point then the L_star is the + * the L_star for the maximum L_star/chroma point. + * This is an error but I return the best approximation I can. + * Thus the inconsistency. + */ + memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + return(XcmsSuccess); + } + + /* + * If the chroma is equal to the chroma for the + * maximum L_star/chroma point then the L_star is the + * the L_star for the maximum L* and chroma point. + */ + /* if (max_chroma == chroma) { + * memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor)); + * return(XcmsSuccess); + * } + */ + + /* must do a bisection here to compute the maximum L* */ + /* save the structure input so that any elements that */ + /* are not touched are recopied later in the routine. */ + nChroma = chroma; + tmp_chroma = max_chroma; + lastChroma = -1.0; + nMaxCount = MAXBISECTCOUNT; + rFactor = 1.0; + + for (nCount = 0; nCount < nMaxCount; nCount++) { + prevChroma = lastChroma; + lastChroma = tmp_chroma; + nT = (1.0 - (nChroma / max_chroma)) * rFactor; + memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor)); + tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT; + tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT; + tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT; + tmp.format = XcmsRGBiFormat; + + /* convert from RGB to CIELuv */ + if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp, + ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + + /* Now check the return against what is expected */ + tmp_chroma = XCMS_CIELUV_PMETRIC_CHROMA(tmp.spec.CIELuv.u_star, + tmp.spec.CIELuv.v_star); + if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) { + /* Found It! */ + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); + } + nChroma += chroma - tmp_chroma; + if (nChroma > max_chroma) { + nChroma = max_chroma; + rFactor *= 0.5; /* selective relaxation employed */ + } else if (nChroma < 0.0) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + return(XcmsSuccess); + } else if (tmp_chroma <= prevChroma + EPS && + tmp_chroma >= prevChroma - EPS) { + rFactor *= 0.5; /* selective relaxation employed */ + } + } + + if (nCount >= nMaxCount) { + if (XCMS_FABS(lastChroma - chroma) < + XCMS_FABS(tmp_chroma - chroma)) { + memcpy ((char *)pColor_return, (char *)&prev, + sizeof(XcmsColor)); + } else { + memcpy ((char *)pColor_return, (char *)&tmp, + sizeof(XcmsColor)); + } + } + memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/LuvMxLC.c b/src/xcms/LuvMxLC.c new file mode 100644 index 0000000..337bbbf --- /dev/null +++ b/src/xcms/LuvMxLC.c @@ -0,0 +1,226 @@ +/* $Xorg: LuvMxLC.c,v 1.3 2000/08/17 19:44:45 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * CIELuvMxVC.c + * + * DESCRIPTION + * Source for the XcmsCIELuvQueryMaxLC() gamut boundary + * querying routine. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + * and + * Fred W. Billmeyer & Max Saltzman, "Principles of Color + * Technology", John Wily & Sons, Inc, 1981. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) +#define START_LSTAR (XcmsFloat)40.0 +#define START_CHROMA (XcmsFloat)2.2 + +/* + * EXTERNS + */ +extern Status _XcmsConvertColorsWithWhitePt(); + +/* + * FORWARD DECLARATIONS + */ +Status _XcmsCIELuvQueryMaxLCRGB(); + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsCIELuvQueryMaxLCRGB - Compute maximum L* and chroma. + * + * SYNOPSIS + */ +Status +_XcmsCIELuvQueryMaxLCRGB(ccc, hue, pColor_return, pRGB_return) + XcmsCCC ccc; + XcmsFloat hue; /* hue in radians */ + XcmsColor *pColor_return; + XcmsRGBi *pRGB_return; + +/* + * DESCRIPTION + * Return the maximum psychometric chroma for a specified + * hue angle(radians), and the corresponding L*. This is computed + * by a binary search of all possible chromas. An assumption + * is made that there are no local maxima. Use the unrounded + * Max psychometric chroma because the difference check can be + * small. + * + * NOTE: No local CCC is used because this is a private + * routine and all routines that call it are expected + * to behave properly, i.e. send a local CCC with + * no white adjust function and no gamut compression + * function. + * + * This routine only accepts hue as input and outputs + * Luv and RGBi. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsFloat nSmall, nLarge; + XcmsColor tmp; + + tmp.format = XcmsCIELuvFormat; + /* Use some unreachable color on the given hue angle */ + tmp.spec.CIELuv.L_star = START_LSTAR; + tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, START_CHROMA); + tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, START_CHROMA); + /* + * Convert from Luv to RGB + * + * Note that the CIEXYZ to RGBi conversion routine must stuff the + * out of bounds RGBi values in tmp when the ccc->gamutCompProc + * is NULL. + */ + if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, ScreenWhitePointOfCCC(ccc), + (unsigned int)1, XcmsRGBiFormat, (Bool *) NULL) + == XcmsFailure) && tmp.format != XcmsRGBiFormat) { + return (XcmsFailure); + } + + /* Now pick the smallest RGB */ + nSmall = MIN3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Make the smallest RGB equal to zero */ + tmp.spec.RGBi.red -= nSmall; + tmp.spec.RGBi.green -= nSmall; + tmp.spec.RGBi.blue -= nSmall; + + /* Now pick the largest RGB */ + nLarge = MAX3(tmp.spec.RGBi.red, + tmp.spec.RGBi.green, + tmp.spec.RGBi.blue); + /* Scale the RGB values based on the largest one */ + tmp.spec.RGBi.red /= nLarge; + tmp.spec.RGBi.green /= nLarge; + tmp.spec.RGBi.blue /= nLarge; + tmp.format = XcmsRGBiFormat; + + /* If the calling routine wants RGB value give them the ones used. */ + if (pRGB_return) { + pRGB_return->red = tmp.spec.RGBi.red; + pRGB_return->green = tmp.spec.RGBi.green; + pRGB_return->blue = tmp.spec.RGBi.blue; + } + + /* Convert from RGBi to Luv */ + if (_XcmsConvertColorsWithWhitePt(ccc, &tmp, + ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat, (Bool *) NULL) + == XcmsFailure) { + return (XcmsFailure); + } + + memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); + return (XcmsSuccess); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvQueryMaxLC - Compute maximum L* and chroma. + * + * SYNOPSIS + */ +Status +XcmsCIELuvQueryMaxLC (ccc, hue_angle, pColor_return) + XcmsCCC ccc; + XcmsFloat hue_angle; /* hue angle in degrees */ + XcmsColor *pColor_return; + +/* + * DESCRIPTION + * Return the point of maximum chroma for the specified + * hue angle. + * + * ASSUMPTIONS + * This routine assumes that the white point associated with + * the color specification is the Screen White Point. The + * Screen White Point will also be associated with the + * returned color specification. + * + * RETURNS + * XcmsFailure - Failure + * XcmsSuccess - Succeeded + * + */ +{ + XcmsCCCRec myCCC; + + /* + * Check Arguments + */ + if (ccc == NULL || pColor_return == NULL) { + return(XcmsFailure); + } + + /* Use my own CCC */ + memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); + myCCC.clientWhitePt.format = XcmsUndefinedFormat; + myCCC.gamutCompProc = (XcmsCompressionProc)NULL; + + while (hue_angle < 0.0) { + hue_angle += 360.0; + } + while (hue_angle >= 360.0) { + hue_angle -= 360.0; + } + + return(_XcmsCIELuvQueryMaxLCRGB (&myCCC, radians(hue_angle), pColor_return, + (XcmsRGBi *)NULL)); +} diff --git a/src/xcms/LuvWpAj.c b/src/xcms/LuvWpAj.c new file mode 100644 index 0000000..5083ccb --- /dev/null +++ b/src/xcms/LuvWpAj.c @@ -0,0 +1,100 @@ +/* $Xorg: LuvWpAj.c,v 1.3 2000/08/17 19:44:45 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * CIELuvWpAj.c + * + * DESCRIPTION + * This file contains routine(s) that support white point + * adjustment of color specifications in the CIE CIELuv.color + * space. + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ + +extern Status _XcmsConvertColorsWithWhitePt(); + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELuvWhiteShiftColors + * + * SYNOPSIS + */ +Status +XcmsCIELuvWhiteShiftColors(ccc, pWhitePtFrom, pWhitePtTo, destSpecFmt, + pColors_in_out, nColors, pCompressed) + XcmsCCC ccc; + XcmsColor *pWhitePtFrom; + XcmsColor *pWhitePtTo; + XcmsColorFormat destSpecFmt; + XcmsColor *pColors_in_out; + unsigned int nColors; + Bool *pCompressed; +/* + * DESCRIPTION + * Adjusts color specifications in an array of XcmsColor + * structures for white point differences. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded without gamut compression, + * XcmsSuccessWithCompression if succeeded with + * gamut compression. + */ +{ + if (pWhitePtFrom == NULL || pWhitePtTo == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Convert to CIELuv using pWhitePtFrom + * We can ignore return value for compression because we are converting + * to XcmsCIELuvFormat which is device-independent, not device-dependent. + */ + if (_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePtFrom, + nColors, XcmsCIELuvFormat, pCompressed) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Convert from CIELuv to destSpecFmt using pWhitePtTo + */ + return(_XcmsConvertColorsWithWhitePt(ccc, pColors_in_out, pWhitePtTo, + nColors, destSpecFmt, pCompressed)); +} diff --git a/src/xcms/OfCCC.c b/src/xcms/OfCCC.c new file mode 100644 index 0000000..20d3a9b --- /dev/null +++ b/src/xcms/OfCCC.c @@ -0,0 +1,160 @@ +/* $Xorg: OfCCC.c,v 1.3 2000/08/17 19:44:47 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsOfCCC.c - Color Conversion Context Querying Routines + * + * DESCRIPTION + * Routines to query components of a Color Conversion + * Context structure. + * + * + */ + +#include "Xlib.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsDisplayOfCCC + * + * SYNOPSIS + */ + +Display * +XcmsDisplayOfCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Queries the Display of the specified CCC. + * + * RETURNS + * Pointer to the Display. + * + */ +{ + return(ccc->dpy); +} + + +/* + * NAME + * XcmsVisualOfCCC + * + * SYNOPSIS + */ + +Visual * +XcmsVisualOfCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Queries the Visual of the specified CCC. + * + * RETURNS + * Pointer to the Visual. + * + */ +{ + return(ccc->visual); +} + + +/* + * NAME + * XcmsScreenNumberOfCCC + * + * SYNOPSIS + */ + +int +XcmsScreenNumberOfCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Queries the screen number of the specified CCC. + * + * RETURNS + * screen number. + * + */ +{ + return(ccc->screenNumber); +} + + +/* + * NAME + * XcmsScreenWhitePointOfCCC + * + * SYNOPSIS + */ + +XcmsColor * +XcmsScreenWhitePointOfCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Queries the screen white point of the specified CCC. + * + * RETURNS + * Pointer to the XcmsColor containing the screen white point. + * + */ +{ + return(&ccc->pPerScrnInfo->screenWhitePt); +} + + +/* + * NAME + * XcmsClientWhitePointOfCCC + * + * SYNOPSIS + */ + +XcmsColor * +XcmsClientWhitePointOfCCC(ccc) + XcmsCCC ccc; +/* + * DESCRIPTION + * Queries the client white point of the specified CCC. + * + * RETURNS + * Pointer to the XcmsColor containing the client white point. + * + */ +{ + return(&ccc->clientWhitePt); +} diff --git a/src/xcms/PrOfId.c b/src/xcms/PrOfId.c new file mode 100644 index 0000000..7b301e4 --- /dev/null +++ b/src/xcms/PrOfId.c @@ -0,0 +1,107 @@ +/* $Xorg: PrOfId.c,v 1.3 2000/08/17 19:44:48 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsPrOfId.c + * + * DESCRIPTION + * Source for XcmsPrefixOfFormat() + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern XcmsColorSpace **_XcmsDIColorSpaces; +extern XcmsColorSpace **_XcmsDDColorSpaces; + + +/* + * NAME + * XcmsPrefixOfId + * + * SYNOPSIS + */ +char * +XcmsPrefixOfFormat(id) + XcmsColorFormat id; +/* + * DESCRIPTION + * Returns the color space prefix for the specified color + * space ID if the color space is found in the Color + * Conversion Context. + * + * RETURNS + * Returns a color space prefix. + * + * CAVEATS + * Space is allocated for the returned string, therefore, + * the application is responsible for freeing (using XFree) + * the space. + * + */ +{ + XcmsColorSpace **papColorSpaces; + char *prefix; + + /* + * First try Device-Independent color spaces + */ + papColorSpaces = _XcmsDIColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + prefix = (char *)Xmalloc((strlen((*papColorSpaces)->prefix) + + 1) * sizeof(char)); + strcpy(prefix, (*papColorSpaces)->prefix); + return(prefix); + } + papColorSpaces++; + } + } + + /* + * Next try Device-Dependent color spaces + */ + papColorSpaces = _XcmsDDColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if ((*papColorSpaces)->id == id) { + prefix = (char *)Xmalloc((strlen((*papColorSpaces)->prefix) + + 1) * sizeof(char)); + strcpy(prefix, (*papColorSpaces)->prefix); + return(prefix); + } + papColorSpaces++; + } + } + + return(NULL); +} diff --git a/src/xcms/QBlack.c b/src/xcms/QBlack.c new file mode 100644 index 0000000..c54dccb --- /dev/null +++ b/src/xcms/QBlack.c @@ -0,0 +1,82 @@ +/* $Xorg: QBlack.c,v 1.3 2000/08/17 19:44:49 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQBlack.c - Query Black + * + * DESCRIPTION + * Routine to obtain a color specification for zero + * red, green, and blue intensities. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryBlack + * + * SYNOPSIS + */ + +Status +XcmsQueryBlack(ccc, target_format, pColor_ret) + XcmsCCC ccc; + XcmsColorFormat target_format; + XcmsColor *pColor_ret; +/* + * DESCRIPTION + * Returns the color specification in the target format for + * zero intensity red, green, and blue. + * + * RETURNS + * Returns XcmsSuccess, if failed; otherwise XcmsFailure + * + */ +{ + XcmsColor tmp; + + tmp.format = XcmsRGBiFormat; + tmp.pixel = 0; + tmp.spec.RGBi.red = 0.0; + tmp.spec.RGBi.green = 0.0; + tmp.spec.RGBi.blue = 0.0; + if (XcmsConvertColors(ccc, &tmp, 1, target_format, NULL) != XcmsSuccess) { + return(XcmsFailure); + } + memcpy((char *)pColor_ret, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/QBlue.c b/src/xcms/QBlue.c new file mode 100644 index 0000000..2bca387 --- /dev/null +++ b/src/xcms/QBlue.c @@ -0,0 +1,82 @@ +/* $Xorg: QBlue.c,v 1.3 2000/08/17 19:44:49 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQBlue.c - Query Blue + * + * DESCRIPTION + * Routine to obtain a color specification for full + * blue intensity and zero red and green intensities. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryBlue + * + * SYNOPSIS + */ + +Status +XcmsQueryBlue(ccc, target_format, pColor_ret) + XcmsCCC ccc; + XcmsColorFormat target_format; + XcmsColor *pColor_ret; +/* + * DESCRIPTION + * Returns the color specification in the target format for + * full intensity blue and zero intensity red and green. + * + * RETURNS + * Returns XcmsSuccess, if failed; otherwise XcmsFailure + * + */ +{ + XcmsColor tmp; + + tmp.format = XcmsRGBiFormat; + tmp.pixel = 0; + tmp.spec.RGBi.red = 0.0; + tmp.spec.RGBi.green = 0.0; + tmp.spec.RGBi.blue = 1.0; + if (XcmsConvertColors(ccc, &tmp, 1, target_format, NULL) != XcmsSuccess) { + return(XcmsFailure); + } + memcpy((char *)pColor_ret, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/QGreen.c b/src/xcms/QGreen.c new file mode 100644 index 0000000..f7858c3 --- /dev/null +++ b/src/xcms/QGreen.c @@ -0,0 +1,82 @@ +/* $Xorg: QGreen.c,v 1.3 2000/08/17 19:44:49 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQGreen.c - Query Green + * + * DESCRIPTION + * Routine to obtain a color specification for full + * green intensity and zero red and blue intensities. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryGreen + * + * SYNOPSIS + */ + +Status +XcmsQueryGreen(ccc, target_format, pColor_ret) + XcmsCCC ccc; + XcmsColorFormat target_format; + XcmsColor *pColor_ret; +/* + * DESCRIPTION + * Returns the color specification in the target format for + * full intensity green and zero intensity red and blue. + * + * RETURNS + * Returns XcmsSuccess, if failed; otherwise XcmsFailure + * + */ +{ + XcmsColor tmp; + + tmp.format = XcmsRGBiFormat; + tmp.pixel = 0; + tmp.spec.RGBi.red = 0.0; + tmp.spec.RGBi.green = 1.0; + tmp.spec.RGBi.blue = 0.0; + if (XcmsConvertColors(ccc, &tmp, 1, target_format, NULL) != XcmsSuccess) { + return(XcmsFailure); + } + memcpy((char *)pColor_ret, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/QRed.c b/src/xcms/QRed.c new file mode 100644 index 0000000..136ebc2 --- /dev/null +++ b/src/xcms/QRed.c @@ -0,0 +1,82 @@ +/* $Xorg: QRed.c,v 1.3 2000/08/17 19:44:49 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQRed.c - Query Red + * + * DESCRIPTION + * Routine to obtain a color specification for full + * red intensity and zero green and blue intensities. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryRed + * + * SYNOPSIS + */ + +Status +XcmsQueryRed(ccc, target_format, pColor_ret) + XcmsCCC ccc; + XcmsColorFormat target_format; + XcmsColor *pColor_ret; +/* + * DESCRIPTION + * Returns the color specification in the target format for + * full intensity red and zero intensity green and blue. + * + * RETURNS + * Returns XcmsSuccess, if failed; otherwise XcmsFailure + * + */ +{ + XcmsColor tmp; + + tmp.format = XcmsRGBiFormat; + tmp.pixel = 0; + tmp.spec.RGBi.red = 1.0; + tmp.spec.RGBi.green = 0.0; + tmp.spec.RGBi.blue = 0.0; + if (XcmsConvertColors(ccc, &tmp, 1, target_format, NULL) != XcmsSuccess) { + return(XcmsFailure); + } + memcpy((char *)pColor_ret, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/QWhite.c b/src/xcms/QWhite.c new file mode 100644 index 0000000..93d37d3 --- /dev/null +++ b/src/xcms/QWhite.c @@ -0,0 +1,82 @@ +/* $Xorg: QWhite.c,v 1.3 2000/08/17 19:44:49 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQWhite.c - Query White + * + * DESCRIPTION + * Routine to obtain a color specification for full + * red, green, and blue intensities. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryWhite + * + * SYNOPSIS + */ + +Status +XcmsQueryWhite(ccc, target_format, pColor_ret) + XcmsCCC ccc; + XcmsColorFormat target_format; + XcmsColor *pColor_ret; +/* + * DESCRIPTION + * Returns the color specification in the target format for + * full intensity red, green, and blue. + * + * RETURNS + * Returns XcmsSuccess, if failed; otherwise XcmsFailure + * + */ +{ + XcmsColor tmp; + + tmp.format = XcmsRGBiFormat; + tmp.pixel = 0; + tmp.spec.RGBi.red = 1.0; + tmp.spec.RGBi.green = 1.0; + tmp.spec.RGBi.blue = 1.0; + if (XcmsConvertColors(ccc, &tmp, 1, target_format, NULL) != XcmsSuccess) { + return(XcmsFailure); + } + memcpy((char *)pColor_ret, (char *)&tmp, sizeof(XcmsColor)); + return(XcmsSuccess); +} diff --git a/src/xcms/QuCol.c b/src/xcms/QuCol.c new file mode 100644 index 0000000..d632d45 --- /dev/null +++ b/src/xcms/QuCol.c @@ -0,0 +1,76 @@ +/* $Xorg: QuCol.c,v 1.3 2000/08/17 19:44:50 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQuCol.c + * + * DESCRIPTION + * Source for XcmsQueryColors + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsQueryColor - Query Color + * + * SYNOPSIS + */ +Status +XcmsQueryColor(dpy, colormap, pXcmsColor_in_out, result_format) + Display *dpy; + Colormap colormap; + XcmsColor *pXcmsColor_in_out; + XcmsColorFormat result_format; +/* + * DESCRIPTION + * This routine uses XQueryColor to obtain the X RGB values + * stored in the specified colormap for the specified pixel. + * The X RGB values are then converted to the target format as + * specified by the format component of the XcmsColor structure. + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded. + * + * Returns a color specification of the color stored in the + * specified pixel. + */ +{ + return(_XcmsSetGetColors (XQueryColor, dpy, colormap, + pXcmsColor_in_out, 1, result_format, (Bool *) NULL)); +} diff --git a/src/xcms/QuCols.c b/src/xcms/QuCols.c new file mode 100644 index 0000000..9a35cf0 --- /dev/null +++ b/src/xcms/QuCols.c @@ -0,0 +1,75 @@ +/* $Xorg: QuCols.c,v 1.3 2000/08/17 19:44:50 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsQuCol.c + * + * DESCRIPTION + * Source for XcmsQueryColors + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ +/* + * NAME + * XcmsQueryColors - Query Colors + * + * SYNOPSIS + */ +Status +XcmsQueryColors(dpy, colormap, pXcmsColors_in_out, nColors, result_format) + Display *dpy; + Colormap colormap; + XcmsColor *pXcmsColors_in_out; + unsigned int nColors; + XcmsColorFormat result_format; +/* + * DESCRIPTION + * This routine uses XQueryColors to obtain the X RGB values + * stored in the specified colormap for the specified pixels. + * The X RGB values are then converted to the target format as + * specified by the format component of the XcmsColor structure. + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded. + * + * Returns the color specifications of the colors stored in the + * specified pixels. + */ +{ + return(_XcmsSetGetColors (XQueryColors, dpy, colormap, + pXcmsColors_in_out, nColors, result_format, (Bool *) NULL)); +} diff --git a/src/xcms/SetCCC.c b/src/xcms/SetCCC.c new file mode 100644 index 0000000..d58daf8 --- /dev/null +++ b/src/xcms/SetCCC.c @@ -0,0 +1,150 @@ +/* $Xorg: SetCCC.c,v 1.3 2000/08/17 19:44:52 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsSetCCC.c - Color Conversion Context Setting Routines + * + * DESCRIPTION + * Routines to set components of a Color Conversion + * Context structure. + * + * + */ + +#include "Xlibint.h" +#include "Xcms.h" + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsSetWhitePoint + * + * SYNOPSIS + */ + +Status +XcmsSetWhitePoint(ccc, pColor) + XcmsCCC ccc; + XcmsColor *pColor; +/* + * DESCRIPTION + * Sets the Client White Point in the specified CCC. + * + * RETURNS + * Returns XcmsSuccess if succeeded; otherwise XcmsFailure. + * + */ +{ + if (pColor == NULL || pColor->format == XcmsUndefinedFormat) { + ccc->clientWhitePt.format = XcmsUndefinedFormat; + } else if (pColor->format != XcmsCIEXYZFormat && + pColor->format != XcmsCIEuvYFormat && + pColor->format != XcmsCIExyYFormat) { + return(XcmsFailure); + } else { + memcpy((char *)&ccc->clientWhitePt, (char *)pColor, sizeof(XcmsColor)); + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsSetCompressionProc + * + * SYNOPSIS + */ + +XcmsCompressionProc +#if NeedFunctionPrototypes +XcmsSetCompressionProc( + XcmsCCC ccc, + XcmsCompressionProc compression_proc, + XPointer client_data) +#else +XcmsSetCompressionProc(ccc, compression_proc, client_data) + XcmsCCC ccc; + XcmsCompressionProc compression_proc; + XPointer client_data; +#endif +/* + * DESCRIPTION + * Set the specified CCC's compression function and client data. + * + * RETURNS + * Returns the old compression function. + * + */ +{ + XcmsCompressionProc old = ccc->gamutCompProc; + + ccc->gamutCompProc = compression_proc; + ccc->gamutCompClientData = client_data; + return(old); +} + + +/* + * NAME + * XcmsSetWhiteAdjustProc + * + * SYNOPSIS + */ + +XcmsWhiteAdjustProc +#if NeedFunctionPrototypes +XcmsSetWhiteAdjustProc( + XcmsCCC ccc, + XcmsWhiteAdjustProc white_adjust_proc, + XPointer client_data ) +#else +XcmsSetWhiteAdjustProc(ccc, white_adjust_proc, client_data) + XcmsCCC ccc; + XcmsWhiteAdjustProc white_adjust_proc; + XPointer client_data; +#endif +/* + * DESCRIPTION + * Set the specified CCC's white_adjust function and client data. + * + * RETURNS + * Returns the old white_adjust function. + * + */ +{ + XcmsWhiteAdjustProc old = ccc->whitePtAdjProc; + + ccc->whitePtAdjProc = white_adjust_proc; + ccc->whitePtAdjClientData = client_data; + return(old); +} diff --git a/src/xcms/SetGetCols.c b/src/xcms/SetGetCols.c new file mode 100644 index 0000000..5ee6898 --- /dev/null +++ b/src/xcms/SetGetCols.c @@ -0,0 +1,201 @@ +/* $Xorg: SetGetCols.c,v 1.3 2000/08/17 19:44:54 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsSetGet.c + * + * DESCRIPTION + * Source for _XcmsSetGetColors() + * + * + */ + +/* + * EXTERNAL INCLUDES + * Include files that must be exported to any package or + * program using this package. + */ +#include "Xlibint.h" +#include "Xcmsint.h" + + +/* + * EXTERNS + */ + +extern void _XcmsRGB_to_XColor(); +extern void _XColor_to_XcmsRGB(); + + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsSetColors - + * + * SYNOPSIS + */ +Status +_XcmsSetGetColors(xColorProc, dpy, cmap, pColors_in_out, nColors, + result_format, pCompressed) + Status (*xColorProc)(); + Display *dpy; + Colormap cmap; + XcmsColor *pColors_in_out; + unsigned int nColors; + XcmsColorFormat result_format; + Bool *pCompressed; +/* + * DESCRIPTION + * Routine containing code common to: + * XcmsAllocColor + * XcmsQueryColor + * XcmsQueryColors + * XcmsStoreColor + * XcmsStoreColors + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded without gamut compression; + * XcmsSuccessWithCompression if it succeeded with gamut + * compression; + */ +{ + XcmsCCC ccc; + XColor *pXColors_in_out; + Status retval = XcmsSuccess; + + /* + * Argument Checking + * 1. Assume xColorProc is correct + * 2. Insure ccc not NULL + * 3. Assume cmap correct (should be checked by Server) + * 4. Insure pColors_in_out valid + * 5. Assume method_in is valid (should be checked by Server) + * 6. Insure nColors > 0 + */ + + if (dpy == NULL) { + return(XcmsFailure); + } + + if (nColors == 0) { + return(XcmsSuccess); + } + + if (result_format == XcmsUndefinedFormat) { + return(XcmsFailure); + } + + if (!((*xColorProc == XAllocColor) || (*xColorProc == XStoreColor) + || (*xColorProc == XStoreColors) || (*xColorProc == XQueryColor) + || (*xColorProc == XQueryColors))) { + return(XcmsFailure); + } + + if ((ccc = XcmsCCCOfColormap(dpy, cmap)) == (XcmsCCC)NULL) { + return(XcmsFailure); + } + + if ((*xColorProc == XAllocColor) || (*xColorProc == XStoreColor) + || (*xColorProc == XQueryColor)) { + nColors = 1; + } + + /* + * Allocate space for XColors + */ + if ((pXColors_in_out = (XColor *)Xcalloc(nColors, sizeof(XColor))) == + NULL) { + return(XcmsFailure); + } + + if ((*xColorProc == XQueryColor) || (*xColorProc == XQueryColors)) { + goto Query; + } + /* + * Convert to RGB, adjusting for white point differences if necessary. + */ + if ((retval = XcmsConvertColors(ccc, pColors_in_out, nColors, XcmsRGBFormat, + pCompressed)) == XcmsFailure) { + return(XcmsFailure); + } + +Query: + /* + * Convert XcmsColor to XColor structures + */ + _XcmsRGB_to_XColor(pColors_in_out, pXColors_in_out, nColors); + + /* + * Now make appropriate X Call + */ + if (*xColorProc == XAllocColor) { + if ((*xColorProc)(ccc->dpy, cmap, pXColors_in_out) == 0) { + Xfree((char *)pXColors_in_out); + return(XcmsFailure); + } + } else if ((*xColorProc == XQueryColor) || (*xColorProc == XStoreColor)) { + /* Note: XQueryColor and XStoreColor do not return any Status */ + (*xColorProc)(ccc->dpy, cmap, pXColors_in_out); + } else if ((*xColorProc == XQueryColors) || (*xColorProc == XStoreColors)){ + /* Note: XQueryColors and XStoreColors do not return any Status */ + (*xColorProc)(ccc->dpy, cmap, pXColors_in_out, nColors); + } else { + Xfree((char *)pXColors_in_out); + return(XcmsFailure); + } + + if ((*xColorProc == XStoreColor) || (*xColorProc == XStoreColors)) { + Xfree((char *)pXColors_in_out); + return(retval); + } + + /* + * Now, convert returned XColor(i.e., rgb) to XcmsColor structures + */ + _XColor_to_XcmsRGB(ccc, pXColors_in_out, pColors_in_out, nColors); + Xfree((char *)pXColors_in_out); + + /* + * Then, convert XcmsColor structures to the original specification + * format. Note that we must use NULL instead of passing + * pCompressed. + */ + + if (result_format != XcmsRGBFormat) { + if (XcmsConvertColors(ccc, pColors_in_out, nColors, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + } + return(retval); +} diff --git a/src/xcms/StCol.c b/src/xcms/StCol.c new file mode 100644 index 0000000..b6229f9 --- /dev/null +++ b/src/xcms/StCol.c @@ -0,0 +1,79 @@ +/* $Xorg: StCol.c,v 1.3 2000/08/17 19:44:55 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsStCol.c + * + * DESCRIPTION + * Source for XcmsStoreColor + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsStoreColor - Store Color + * + * SYNOPSIS + */ +Status +XcmsStoreColor(dpy, colormap, pColor_in) + Display *dpy; + Colormap colormap; + XcmsColor *pColor_in; +/* + * DESCRIPTION + * Given a device-dependent or device-independent color + * specification, this routine will convert it to X RGB + * values then use it in a call to XStoreColor. + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded without gamut compression; + * XcmsSuccessWithCompression if it succeeded with gamut + * compression; + * + * Since XStoreColor has no return value this routine + * does not return the color specification of the color actually + * stored. + */ +{ + XcmsColor tmpColor; + + tmpColor = *pColor_in; + return(_XcmsSetGetColors (XStoreColor, dpy, colormap, + &tmpColor, 1, XcmsRGBFormat, (Bool *) NULL)); +} diff --git a/src/xcms/StCols.c b/src/xcms/StCols.c new file mode 100644 index 0000000..1e833c3 --- /dev/null +++ b/src/xcms/StCols.c @@ -0,0 +1,110 @@ +/* $Xorg: StCols.c,v 1.3 2000/08/17 19:44:56 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsStCols.c + * + * DESCRIPTION + * Source for XcmsStoreColors + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsStoreColors - Store Colors + * + * SYNOPSIS + */ +Status +XcmsStoreColors(dpy, colormap, pColors_in, + nColors, pCompressed) + Display *dpy; + Colormap colormap; + XcmsColor *pColors_in; + unsigned int nColors; + Bool *pCompressed; +/* + * DESCRIPTION + * Given device-dependent or device-independent color + * specifications, this routine will convert them to X RGB + * values then use it in a call to XStoreColors. + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded without gamut compression; + * XcmsSuccessWithCompression if it succeeded with gamut + * compression; + * + * Since XStoreColors has no return value, this routine + * does not return color specifications of the colors actually + * stored. + */ +{ + XcmsColor Color1; + XcmsColor *pColors_tmp; + Status retval; + + /* + * Make copy of array of color specifications so we don't + * overwrite the contents. + */ + if (nColors > 1) { + pColors_tmp = (XcmsColor *) Xmalloc(nColors * sizeof(XcmsColor)); + } else { + pColors_tmp = &Color1; + } + memcpy((char *)pColors_tmp, (char *)pColors_in, + nColors * sizeof(XcmsColor)); + + /* + * Call routine to store colors using the copied color structures + */ + retval = _XcmsSetGetColors (XStoreColors, dpy, colormap, + pColors_tmp, nColors, XcmsRGBFormat, pCompressed); + + /* + * Free copies as needed. + */ + if (nColors > 1) { + Xfree((char *)pColors_tmp); + } + + /* + * Ah, finally return. + */ + return(retval); +} diff --git a/src/xcms/UNDEFINED.c b/src/xcms/UNDEFINED.c new file mode 100644 index 0000000..a4e0555 --- /dev/null +++ b/src/xcms/UNDEFINED.c @@ -0,0 +1,102 @@ +/* $Xorg: UNDEFINED.c,v 1.3 2000/08/17 19:44:57 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * UNDEFINED.c + * + * DESCRIPTION + * UNDEFINED Color Space + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * FORWARD DECLARATIONS + */ +static int ReturnZero(); + + +/* + * LOCALS VARIABLES + */ + +static Status (*(Fl_ReturnZero[]))() = { + ReturnZero, + NULL +}; + + + + +/* + * GLOBALS + * Variables declared in this package that are allowed + * to be used globally. + */ + /* + * UNDEFINED Color Space + */ +XcmsColorSpace XcmsUNDEFINEDColorSpace = + { + "undefined", /* prefix */ + XcmsUndefinedFormat, /* id */ + ReturnZero, /* parseString */ + Fl_ReturnZero, /* to_CIEXYZ */ + Fl_ReturnZero /* from_CIEXYZ */ + }; + + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * ReturnZero + * + * SYNOPSIS + */ +/* ARGSUSED */ +static int +ReturnZero() +/* + * DESCRIPTION + * Does nothing. + * + * RETURNS + * 0 + * + */ +{ + return(0); +} diff --git a/src/xcms/XRGB.c b/src/xcms/XRGB.c new file mode 100644 index 0000000..7e5b7f8 --- /dev/null +++ b/src/xcms/XRGB.c @@ -0,0 +1,245 @@ +/* $Xorg: XRGB.c,v 1.3 2000/08/17 19:45:04 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsRtoX.c + * + * DESCRIPTION + * Convert color specifications in XcmsRGB format in one array of + * XcmsColor structures to RGB in an array of XColor structures. + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +#ifdef __STDC__ +#define Const const +#else +#define Const /**/ +#endif + +/* + * LOCAL VARIABLES + */ + +static unsigned short Const MASK[17] = { + 0x0000, /* 0 bitsPerRGB */ + 0x8000, /* 1 bitsPerRGB */ + 0xc000, /* 2 bitsPerRGB */ + 0xe000, /* 3 bitsPerRGB */ + 0xf000, /* 4 bitsPerRGB */ + 0xf800, /* 5 bitsPerRGB */ + 0xfc00, /* 6 bitsPerRGB */ + 0xfe00, /* 7 bitsPerRGB */ + 0xff00, /* 8 bitsPerRGB */ + 0xff80, /* 9 bitsPerRGB */ + 0xffc0, /* 10 bitsPerRGB */ + 0xffe0, /* 11 bitsPerRGB */ + 0xfff0, /* 12 bitsPerRGB */ + 0xfff8, /* 13 bitsPerRGB */ + 0xfffc, /* 14 bitsPerRGB */ + 0xfffe, /* 15 bitsPerRGB */ + 0xffff /* 16 bitsPerRGB */ +}; + + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsRGB_to_XColor - + * + * SYNOPSIS + */ +void +_XcmsRGB_to_XColor(pColors, pXColors, nColors) + XcmsColor *pColors; + XColor *pXColors; + unsigned int nColors; +/* + * DESCRIPTION + * Translates a color specification in XcmsRGBFormat in a XcmsColor + * structure to an XColor structure. + * + * RETURNS + * void. + */ +{ + for (; nColors--; pXColors++, pColors++) { + pXColors->pixel = pColors->pixel; + pXColors->red = pColors->spec.RGB.red; + pXColors->green = pColors->spec.RGB.green; + pXColors->blue = pColors->spec.RGB.blue; + pXColors->flags = (DoRed | DoGreen | DoBlue); + } +} + + +/* + * NAME + * _XColor_to_XcmsRGB + * + * SYNOPSIS + */ +void +_XColor_to_XcmsRGB(ccc, pXColors, pColors, nColors) + XcmsCCC ccc; + XColor *pXColors; + XcmsColor *pColors; + unsigned int nColors; +/* + * DESCRIPTION + * Translates an RGB color specification in an XColor + * structure to an XcmsRGB structure. + * + * IMPORTANT NOTE: Bit replication that may have been caused + * with ResolveColor() routine in the X Server is undone + * here if requested! For example, if red = 0xcaca and the + * bits_per_rgb is 8, then spec.RGB.red will be 0xca00. + * + * RETURNS + * void + */ +{ + int bits_per_rgb = ccc->visual->bits_per_rgb; + + for (; nColors--; pXColors++, pColors++) { + pColors->spec.RGB.red = (pXColors->red & MASK[bits_per_rgb]); + pColors->spec.RGB.green = (pXColors->green & MASK[bits_per_rgb]); + pColors->spec.RGB.blue = (pXColors->blue & MASK[bits_per_rgb]); + pColors->format = XcmsRGBFormat; + pColors->pixel = pXColors->pixel; + } +} + + +/* + * NAME + * _XcmsResolveColor + * + * SYNOPSIS + */ +void +_XcmsResolveColor(ccc, pXcmsColor) + XcmsCCC ccc; + XcmsColor *pXcmsColor; +/* + * DESCRIPTION + * Uses the X Server ResolveColor() algorithm to + * modify values to closest values supported by hardware. + * Old algorithm simply masked low-order bits. The new algorithm + * has the effect of replicating significant bits into lower order + * bits in order to stretch the hardware value into all 16 bits. + * + * On a display with N-bit DACs, the "hardware" color is computed as: + * + * ((unsignedlong)(ClientValue >> (16-N)) * 0xFFFF) / ((1 << N) - 1) + * + * + * RETURNS + * void. + */ +{ + int shift; + int max_color; + + shift = 16 - ccc->visual->bits_per_rgb; + max_color = (1 << ccc->visual->bits_per_rgb) - 1; + + + pXcmsColor->spec.RGB.red = + ((unsigned long)(pXcmsColor->spec.RGB.red >> shift) * 0xFFFF) + / max_color; + pXcmsColor->spec.RGB.green = + ((unsigned long)(pXcmsColor->spec.RGB.green >> shift) * 0xFFFF) + / max_color; + pXcmsColor->spec.RGB.blue = + ((unsigned long)(pXcmsColor->spec.RGB.blue >> shift) * 0xFFFF) + / max_color; +} + + +/* + * NAME + * _XcmsUnresolveColor + * + * SYNOPSIS + */ +void +_XcmsUnresolveColor(ccc, pColor) + XcmsCCC ccc; + XcmsColor *pColor; +/* + * DESCRIPTION + * Masks out insignificant bits. + * + * RETURNS + * void. + * + * ASSUMPTIONS + * format == XcmsRGBFormat + */ +{ + int bits_per_rgb = ccc->visual->bits_per_rgb; + + pColor->spec.RGB.red &= MASK[bits_per_rgb]; + pColor->spec.RGB.green &= MASK[bits_per_rgb]; + pColor->spec.RGB.blue &= MASK[bits_per_rgb]; +} + + +/* + * NAME + * _XUnresolveColor + * + * SYNOPSIS + */ +void +_XUnresolveColor(ccc, pXColor) + XcmsCCC ccc; + XColor *pXColor; +/* + * DESCRIPTION + * Masks out insignificant bits. + * + * RETURNS + * void. + */ +{ + int bits_per_rgb = ccc->visual->bits_per_rgb; + + pXColor->red &= MASK[bits_per_rgb]; + pXColor->green &= MASK[bits_per_rgb]; + pXColor->blue &= MASK[bits_per_rgb]; +} + diff --git a/src/xcms/XYZ.c b/src/xcms/XYZ.c new file mode 100644 index 0000000..a06b213 --- /dev/null +++ b/src/xcms/XYZ.c @@ -0,0 +1,192 @@ +/* $Xorg: XYZ.c,v 1.3 2000/08/17 19:45:04 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * + * NAME + * CIEXYZ.c + * + * DESCRIPTION + * CIE XYZ Color Space + * + * + */ + +#include <X11/Xos.h> +#include "Xlibint.h" +#include "Xcmsint.h" + + +/* + * EXTERNS + * External declarations required locally to this package + * that are not already declared in any of the included header + * files (external includes or internal includes). + */ +extern char _XcmsCIEXYZ_prefix[]; + +/* + * DEFINES + * Internal definitions that need NOT be exported to any package + * or program using this package. + */ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif + +/* + * FORWARD DECLARATIONS + */ +static int CIEXYZ_ParseString(); +Status _XcmsCIEXYZ_ValidSpec(); + + +/* + * LOCALS VARIABLES + */ + +static XcmsConversionProc Fl_CIEXYZ_to_CIEXYZ[] = { + NULL +}; + + + +/* + * GLOBALS + * Variables declared in this package that are allowed + * to be used globally. + */ + /* + * CIE XYZ Color Space + */ +XcmsColorSpace XcmsCIEXYZColorSpace = + { + _XcmsCIEXYZ_prefix, /* prefix */ + XcmsCIEXYZFormat, /* id */ + CIEXYZ_ParseString, /* parseString */ + Fl_CIEXYZ_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_CIEXYZ, /* from_CIEXYZ */ + 1 + }; + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIEXYZ_ParseString + * + * SYNOPSIS + */ +static int +CIEXYZ_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsCIEXYZFormat. + * The assumed CIEXYZ string syntax is: + * CIEXYZ:<X>/<Y>/<Z> + * Where X, Y, and Z are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsCIEXYZ_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.CIEXYZ.X, + &pColor->spec.CIEXYZ.Y, + &pColor->spec.CIEXYZ.Z) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsCIEXYZFormat; + pColor->pixel = 0; + return(_XcmsCIEXYZ_ValidSpec(pColor)); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIELab_ValidSpec + * + * SYNOPSIS + */ +Status +_XcmsCIEXYZ_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if color specification valid for CIE XYZ + * + * RETURNS + * XcmsFailure if invalid, + * XcmsSuccess if valid. + * + */ +{ + if (pColor->format != XcmsCIEXYZFormat + || + (pColor->spec.CIEXYZ.Y < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIEXYZ.Y > 1.0 + XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + return(XcmsSuccess); +} diff --git a/src/xcms/Xcms.txt b/src/xcms/Xcms.txt new file mode 100644 index 0000000..c27fd8f --- /dev/null +++ b/src/xcms/Xcms.txt @@ -0,0 +1,61 @@ +/* + * (c) Copyright 1990 1991 Tektronix Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Tektronix not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. + * + * Tektronix disclaims all warranties with regard to this software, including + * all implied warranties of merchantability and fitness, in no event shall + * Tektronix be liable for any special, indirect or consequential damages or + * any damages whatsoever resulting from loss of use, data or profits, + * whether in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of this + * software. + * + * + * NAME + * Xcms.txt + * + * DESCRIPTION + * Sample Color Name Database + * + */ + + +This device-independent color name database is provided just as an example. +There are no claims that these color specifications are or should be bound +to the corresponding color name. + +As you can see, the start of the database is indicated by "XCMS_COLORDB_START". +Anything before this is assumed to be comments. The "0.1" indicates the +version number of the format/syntax used in this file. The color name is +delimited from the color specification by one or more tabs. + +XCMS_COLORDB_START 0.1 +red CIEXYZ:0.371298/0.201443/0.059418 +green CIEXYZ:0.321204/0.660070/0.159833 +blue CIEXYZ:0.279962/0.160195/1.210705 +aquamarine CIEXYZ:0.34672401/0.54832153/0.44658871 +cadet blue CIEXYZ:0.22601070/0.28905571/0.47233452 +cornflower blue CIEXYZ:0.05658276/0.04476296/0.17063955 +navy blue CIEXYZ:0.06713718/0.03366278/0.31293880 +navy CIEXYZ:0.06713718/0.03366278/0.31293880 +brown CIEXYZ:0.08443233/0.06011398/0.01840693 +gray0 TekHVC:0.0/0.0/0.0 +gray10 TekHVC:0.0/10.0/0.0 +gray20 TekHVC:0.0/20.0/0.0 +gray30 TekHVC:0.0/30.0/0.0 +gray40 TekHVC:0.0/40.0/0.0 +gray50 TekHVC:0.0/50.0/0.0 +gray60 TekHVC:0.0/60.0/0.0 +gray70 TekHVC:0.0/70.0/0.0 +gray80 TekHVC:0.0/80.0/0.0 +gray90 TekHVC:0.0/90.0/0.0 +gray100 TekHVC:0.0/100.0/0.0 +XCMS_COLORDB_END diff --git a/src/xcms/Xcmsint.h b/src/xcms/Xcmsint.h new file mode 100644 index 0000000..68cd1b7 --- /dev/null +++ b/src/xcms/Xcmsint.h @@ -0,0 +1,246 @@ +/* $Xorg: Xcmsint.h,v 1.3 2000/08/17 19:45:05 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * DESCRIPTION + * Private include file for Color Management System. + * (i.e., for API internal use only) + * + */ +#ifndef _XCMSINT_H_ +#define _XCMSINT_H_ + +#include <X11/Xcms.h> + +/* + * DEFINES + */ + + /* + * Private Status Value + */ +#define _XCMS_NEWNAME -1 + + /* + * Color Space ID's are of XcmsColorFormat type. + * + * bit 31 + * 0 == Device-Independent + * 1 == Device-Dependent + * + * bit 30: + * 0 == Registered with X Consortium + * 1 == Unregistered + */ +#define XCMS_DD_ID(id) ((id) & (XcmsColorFormat)0x80000000) +#define XCMS_DI_ID(id) (!((id) & (XcmsColorFormat)0x80000000)) +#define XCMS_UNREG_ID(id) ((id) & (XcmsColorFormat)0x40000000) +#define XCMS_REG_ID(id) (!((id) & (XcmsColorFormat)0x40000000)) +#define XCMS_FIRST_REG_DI_ID (XcmsColorFormat)0x00000001 +#define XCMS_FIRST_UNREG_DI_ID (XcmsColorFormat)0x40000000 +#define XCMS_FIRST_REG_DD_ID (XcmsColorFormat)0x80000000 +#define XCMS_FIRST_UNREG_DD_ID (XcmsColorFormat)0xc0000000 + +/* + * TYPEDEFS + */ + + /* + * Structure for caching Colormap info. + * This is provided for the Xlib modifications to: + * XAllocNamedColor() + * XLookupColor() + * XParseColor() + * XStoreNamedColor() + */ +typedef struct _XcmsCmapRec { + Colormap cmapID; + Display *dpy; + Window windowID; + Visual *visual; + struct _XcmsCCC *ccc; + struct _XcmsCmapRec *pNext; +} XcmsCmapRec; + + /* + * Intensity Record (i.e., value / intensity tuple) + */ +typedef struct _IntensityRec { + unsigned short value; + XcmsFloat intensity; +} IntensityRec; + + /* + * Intensity Table + */ +typedef struct _IntensityTbl { + IntensityRec *pBase; + unsigned int nEntries; +} IntensityTbl; + + /* + * Structure for storing per-Visual Intensity Tables (aka gamma maps). + */ +typedef struct _XcmsIntensityMap { + VisualID visualID; + XPointer screenData; /* pointer to corresponding Screen Color*/ + /* Characterization Data */ + void (*pFreeScreenData)(); /* Function that frees a Screen */ + /* structure. */ + struct _XcmsIntensityMap *pNext; +} XcmsIntensityMap; + + + /* + * Structure for storing "registered" color space prefix/ID + */ +typedef struct _XcmsRegColorSpaceEntry { + char *prefix; /* Color Space prefix (e.g., "CIEXYZ:") */ + XcmsColorFormat id; /* Color Space ID (e.g., XcmsCIEXYZFormat) */ +} XcmsRegColorSpaceEntry; + + + /* + * Xcms Per Display (i.e. connection) related data + */ +typedef struct _XcmsPerDpyInfo { + + XcmsCCC paDefaultCCC; /* based on default visual of screen */ + /* + * Pointer to an array of XcmsCCC structures, one for + * each screen. + */ + XcmsCmapRec *pClientCmaps; /* Pointer to linked list of XcmsCmapRec's */ + +} XcmsPerDpyInfo, *XcmsPerDpyInfoPtr; + +/* + * DEFINES + */ + +#define XDCCC_NUMBER 0x8000000L /* 2**27 per XDCCC */ + +#ifdef GRAY +#define XDCCC_SCREENWHITEPT_ATOM_NAME "XDCCC_GRAY_SCREENWHITEPOINT" +#define XDCCC_GRAY_CORRECT_ATOM_NAME "XDCCC_GRAY_CORRECTION" +#endif /* GRAY */ + +#ifndef _ConversionValues +typedef struct _ConversionValues { + IntensityTbl IntensityTbl; +} ConversionValues; +#endif + +#ifdef GRAY +typedef struct { + IntensityTbl *IntensityTbl; +} GRAY_SCCData; +#endif /* GRAY */ + +/* + * DEFINES + */ + +#define XDCCC_MATRIX_ATOM_NAME "XDCCC_LINEAR_RGB_MATRICES" +#define XDCCC_CORRECT_ATOM_NAME "XDCCC_LINEAR_RGB_CORRECTION" + +typedef struct { + XcmsFloat XYZtoRGBmatrix[3][3]; + XcmsFloat RGBtoXYZmatrix[3][3]; + IntensityTbl *pRedTbl; + IntensityTbl *pGreenTbl; + IntensityTbl *pBlueTbl; +} LINEAR_RGB_SCCData; + +/* + * DESCRIPTION + * Include file for defining the math macros used in the + * XCMS source. Instead of using math library routines + * directly, XCMS uses macros so that based on the + * definitions here, vendors and sites can specify exactly + * what routine will be called (those from libm.a or their + * custom routines). If not defined to math library routines + * (e.g., sqrt in libm.a), then the client is not forced to + * be linked with -lm. + */ + +#define XCMS_ATAN(x) _XcmsArcTangent(x) +#define XCMS_COS(x) _XcmsCosine(x) +#define XCMS_CUBEROOT(x) _XcmsCubeRoot(x) +#define XCMS_FABS(x) ((x) < 0.0 ? -(x) : (x)) +#define XCMS_SIN(x) _XcmsSine(x) +#define XCMS_SQRT(x) _XcmsSquareRoot(x) +#define XCMS_TAN(x) (XCMS_SIN(x) / XCMS_COS(x)) + +#ifdef __STDC__ +double _XcmsArcTangent(double a); +double _XcmsCosine(double a); +double _XcmsCubeRoot(double a); +double _XcmsSine(double a); +double _XcmsSquareRoot(double a); +#else +double _XcmsArcTangent(); +double _XcmsCosine(); +double _XcmsCubeRoot(); +double _XcmsSine(); +double _XcmsSquareRoot(); +#endif + +/* + * DEFINES FOR GAMUT COMPRESSION AND QUERY ROUTINES + */ +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846264338327950 +# endif /* M_PI */ +#endif /* PI */ +#ifndef degrees +# define degrees(r) ((XcmsFloat)(r) * 180.0 / PI) +#endif /* degrees */ +#ifndef radians +# define radians(d) ((XcmsFloat)(d) * PI / 180.0) +#endif /* radians */ + +#define XCMS_CIEUSTAROFHUE(h,c) \ +((XCMS_COS((h)) == 0.0) ? (XcmsFloat)0.0 : (XcmsFloat) \ +((XcmsFloat)(c) / (XcmsFloat)XCMS_SQRT((XCMS_TAN(h) * XCMS_TAN(h)) + \ +(XcmsFloat)1.0))) +#define XCMS_CIEVSTAROFHUE(h,c) \ +((XCMS_COS((h)) == 0.0) ? (XcmsFloat)0.0 : (XcmsFloat) \ +((XcmsFloat)(c) / (XcmsFloat)XCMS_SQRT(((XcmsFloat)1.0 / \ +(XcmsFloat)(XCMS_TAN(h) * XCMS_TAN(h))) + (XcmsFloat)1.0))) +/* this hue is returned in radians */ +#define XCMS_CIELUV_PMETRIC_HUE(u,v) \ +(((u) != 0.0) ? XCMS_ATAN( (v) / (u)) : ((v >= 0.0) ? PI / 2 : -(PI / 2))) +#define XCMS_CIELUV_PMETRIC_CHROMA(u,v) XCMS_SQRT(((u)*(u)) + ((v)*(v))) + +#define XCMS_CIEASTAROFHUE(h,c) XCMS_CIEUSTAROFHUE((h), (c)) +#define XCMS_CIEBSTAROFHUE(h,c) XCMS_CIEVSTAROFHUE((h), (c)) +#define XCMS_CIELAB_PMETRIC_HUE(a,b) XCMS_CIELUV_PMETRIC_HUE((a), (b)) +#define XCMS_CIELAB_PMETRIC_CHROMA(a,b) XCMS_CIELUV_PMETRIC_CHROMA((a), (b)) + +#endif /* _XCMSINT_H_ */ diff --git a/src/xcms/cmsAllCol.c b/src/xcms/cmsAllCol.c new file mode 100644 index 0000000..b631064 --- /dev/null +++ b/src/xcms/cmsAllCol.c @@ -0,0 +1,71 @@ +/* $Xorg: cmsAllCol.c,v 1.3 2000/08/17 19:45:08 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsAllCol.c + * + * DESCRIPTION + * Source for XcmsAllocColor + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + + +/* + * NAME + * XcmsAllocColor - Allocate Color + * + * SYNOPSIS + */ +Status +XcmsAllocColor(dpy, colormap, pXcmsColor_in_out, result_format) + Display *dpy; + Colormap colormap; + XcmsColor *pXcmsColor_in_out; + XcmsColorFormat result_format; +/* + * DESCRIPTION + * Given a device-dependent or device-independent color + * specification, XcmsAllocColor will convert it to X RGB + * values then use it in a call to XAllocColor. + * + * RETURNS + * XcmsFailure if failed; + * XcmsSuccess if it succeeded without gamut compression; + * XcmsSuccessWithCompression if it succeeded with gamut + * compression; + * + * Also returns the pixel value of the color cell and a color + * specification of the color actually stored. + * + */ +{ + return(_XcmsSetGetColors (XAllocColor, dpy, colormap, pXcmsColor_in_out, 1, + result_format, (Bool *)NULL)); +} diff --git a/src/xcms/cmsAllNCol.c b/src/xcms/cmsAllNCol.c new file mode 100644 index 0000000..960173f --- /dev/null +++ b/src/xcms/cmsAllNCol.c @@ -0,0 +1,214 @@ +/* $Xorg: cmsAllNCol.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsAlNCol.c + * + * DESCRIPTION + * Source for XcmsAllocNamedColor + * + * + */ + +#define NEED_REPLIES +#include <stdio.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern void _XColor_to_XcmsRGB(); +extern void _XcmsRGB_to_XColor(); + + +/* + * NAME + * XcmsAllocNamedColor - + * + * SYNOPSIS + */ +#if NeedFunctionPrototypes +Status +XcmsAllocNamedColor ( + Display *dpy, + Colormap cmap, + _Xconst char *colorname, + XcmsColor *pColor_scrn_return, + XcmsColor *pColor_exact_return, + XcmsColorFormat result_format) +#else +Status +XcmsAllocNamedColor(dpy, cmap, colorname, pColor_scrn_return, + pColor_exact_return, result_format) + Display *dpy; + Colormap cmap; + char *colorname; + XcmsColor *pColor_scrn_return; + XcmsColor *pColor_exact_return; + XcmsColorFormat result_format; +#endif +/* + * DESCRIPTION + * Finds the color specification associated with the color + * name in the Device-Independent Color Name Database, then + * converts that color specification to an RGB format. This + * RGB value is then used in a call to XAllocColor to allocate + * a read-only color cell. + * + * RETURNS + * 0 if failed to parse string or find any entry in the database. + * 1 if succeeded in converting color name to XcmsColor. + * 2 if succeeded in converting color name to another color name. + * + */ +{ + long nbytes; + xAllocNamedColorReply rep; + xAllocNamedColorReq *req; + XColor hard_def; + XColor exact_def; + Status retval1 = 1; + Status retval2 = XcmsSuccess; + XcmsColor tmpColor; + XColor XColor_in_out; + XcmsCCC ccc; + + /* + * 0. Check for invalid arguments. + */ + if (dpy == NULL || colorname[0] == '\0' || pColor_scrn_return == 0 + || pColor_exact_return == NULL) { + return(XcmsFailure); + } + + if ((ccc = XcmsCCCOfColormap(dpy, cmap)) == (XcmsCCC)NULL) { + return(XcmsFailure); + } + + /* + * 1. Convert string to a XcmsColor using Xcms and i18n mechanism + */ + if ((retval1 = _XcmsResolveColorString(ccc, &colorname, + &tmpColor, result_format)) == XcmsFailure) { + return(XcmsFailure); + } + if (retval1 == _XCMS_NEWNAME) { + goto PassToServer; + } + memcpy((char *)pColor_exact_return, (char *)&tmpColor, sizeof(XcmsColor)); + + /* + * 2. Convert tmpColor to RGB + * Assume pColor_exact_return is now adjusted to Client White Point + */ + if ((retval2 = XcmsConvertColors(ccc, &tmpColor, + 1, XcmsRGBFormat, (Bool *) NULL)) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * 3. Convert to XColor and call XAllocColor + */ + _XcmsRGB_to_XColor(&tmpColor, &XColor_in_out, 1); + if (XAllocColor(ccc->dpy, cmap, &XColor_in_out) == 0) { + return(XcmsFailure); + } + + /* + * 4. pColor_scrn_return + * + * Now convert to the target format. + * We can ignore the return value because we're already in a + * device-dependent format. + */ + _XColor_to_XcmsRGB(ccc, &XColor_in_out, pColor_scrn_return, 1); + if (result_format != XcmsRGBFormat) { + if (result_format == XcmsUndefinedFormat) { + result_format = pColor_exact_return->format; + } + if (XcmsConvertColors(ccc, pColor_scrn_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + } + + return(retval1 > retval2 ? retval1 : retval2); + +PassToServer: + /* + * All previous methods failed, so lets pass it to the server + * for parsing. + */ + dpy = ccc->dpy; + LockDisplay(dpy); + GetReq(AllocNamedColor, req); + + req->cmap = cmap; + nbytes = req->nbytes = strlen(colorname); + req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */ + + _XSend(dpy, colorname, nbytes); + /* _XSend is more efficient that Data, since _XReply follows */ + + if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return (0); + } + + exact_def.red = rep.exactRed; + exact_def.green = rep.exactGreen; + exact_def.blue = rep.exactBlue; + + hard_def.red = rep.screenRed; + hard_def.green = rep.screenGreen; + hard_def.blue = rep.screenBlue; + + exact_def.pixel = hard_def.pixel = rep.pixel; + + UnlockDisplay(dpy); + SyncHandle(); + + /* + * Now convert to the target format. + */ + _XColor_to_XcmsRGB(ccc, &exact_def, pColor_exact_return, 1); + _XColor_to_XcmsRGB(ccc, &hard_def, pColor_scrn_return, 1); + if (result_format != XcmsRGBFormat + && result_format != XcmsUndefinedFormat) { + if (XcmsConvertColors(ccc, pColor_exact_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + if (XcmsConvertColors(ccc, pColor_scrn_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + } + + return(XcmsSuccess); +} diff --git a/src/xcms/cmsCmap.c b/src/xcms/cmsCmap.c new file mode 100644 index 0000000..84d60a4 --- /dev/null +++ b/src/xcms/cmsCmap.c @@ -0,0 +1,492 @@ +/* $Xorg: cmsCmap.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsCmap.c - Client Colormap Management Routines + * + * DESCRIPTION + * Routines that store additional information about + * colormaps being used by the X Client. + * + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#include "Xlibint.h" +#include "Xcmsint.h" +#include "Xutil.h" + +/* + * FORWARD DECLARATIONS + */ +XcmsCmapRec *_XcmsAddCmapRec(); +static void _XcmsFreeClientCmaps(); + + +/************************************************************************ + * * + * PRIVATE INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * CmapRecForColormap + * + * SYNOPSIS + */ +static XcmsCmapRec * +CmapRecForColormap(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Find the corresponding XcmsCmapRec for cmap. In not found + * this routines attempts to create one. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the corresponding XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pRec; + int nScrn; + int i, j; + XVisualInfo visualTemplate; /* Template of the visual we want */ + XVisualInfo *visualList; /* List for visuals that match */ + int nVisualsMatched; /* Number of visuals that match */ + Window tmpWindow; + Visual *vp; + unsigned long border = 0; + _XAsyncHandler async; + _XAsyncErrorState async_state; + + for (pRec = (XcmsCmapRec *)dpy->cms.clientCmaps; pRec != NULL; + pRec = pRec->pNext) { + if (pRec->cmapID == cmap) { + return(pRec); + } + } + + /* + * Can't find an XcmsCmapRec associated with cmap in our records. + * Let's try to see if its a default colormap + */ + nScrn = ScreenCount(dpy); + for (i = 0; i < nScrn; i++) { + if (cmap == DefaultColormap(dpy, i)) { + /* It is ... lets go ahead and store that info */ + if ((pRec = _XcmsAddCmapRec(dpy, cmap, RootWindow(dpy, i), + DefaultVisual(dpy, i))) == NULL) { + return((XcmsCmapRec *)NULL); + } + pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + DefaultVisual(dpy, i), + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + ); + return(pRec); + } + } + + /* + * Nope, its not a default colormap, so it's probably a foreign color map + * of which we have no specific details. Let's go through the + * rigorous process of finding this colormap: + * for each screen + * for each screen's visual types + * create a window with cmap specified as the colormap + * if successful + * Add a CmapRec + * Create an XcmsCCC + * return the CmapRec + * else + * continue + */ + + async_state.error_code = 0; /* don't care */ + async_state.major_opcode = X_CreateWindow; + async_state.minor_opcode = 0; + for (i = 0; i < nScrn; i++) { + visualTemplate.screen = i; + visualList = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate, + &nVisualsMatched); + if (nVisualsMatched == 0) { + continue; + } + + /* + * Attempt to create a window with cmap + */ + j = 0; + do { + vp = (visualList+j)->visual; + LockDisplay(dpy); + { + register xCreateWindowReq *req; + + GetReq(CreateWindow, req); + async_state.min_sequence_number = dpy->request; + async_state.max_sequence_number = dpy->request; + async_state.error_count = 0; + async.next = dpy->async_handlers; + async.handler = _XAsyncErrorHandler; + async.data = (XPointer)&async_state; + dpy->async_handlers = &async; + req->parent = RootWindow(dpy, i); + req->x = 0; + req->y = 0; + req->width = 1; + req->height = 1; + req->borderWidth = 0; + req->depth = (visualList+j)->depth; + req->class = CopyFromParent; + req->visual = vp->visualid; + tmpWindow = req->wid = XAllocID(dpy); + req->mask = CWBorderPixel | CWColormap; + req->length += 2; + Data32 (dpy, (long *) &border, 4); + Data32 (dpy, (long *) &cmap, 4); + } + { + xGetInputFocusReply rep; + register xReq *req; + + GetEmptyReq(GetInputFocus, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); + } + DeqAsyncHandler(dpy, &async); + UnlockDisplay(dpy); + SyncHandle(); + } while (async_state.error_count > 0 && ++j < nVisualsMatched); + + Xfree((char *)visualList); + + /* + * if successful + */ + if (j < nVisualsMatched) { + if ((pRec = _XcmsAddCmapRec(dpy, cmap, tmpWindow, vp)) == NULL) + return((XcmsCmapRec *)NULL); + pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + vp, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + ); + XDestroyWindow(dpy, tmpWindow); + return(pRec); + } + } + + return(NULL); +} + + + +/************************************************************************ + * * + * API PRIVATE INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsAddCmapRec + * + * SYNOPSIS + */ +XcmsCmapRec * +_XcmsAddCmapRec(dpy, cmap, windowID, visual) + Display *dpy; + Colormap cmap; + Window windowID; + Visual *visual; +/* + * DESCRIPTION + * Create an XcmsCmapRec for the specified cmap, windowID, + * and visual, then adds it to its list of CmapRec's. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the added XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pNew; + + if ((pNew = (XcmsCmapRec *) Xcalloc(1, (unsigned) sizeof(XcmsCmapRec))) + == NULL) { + return((XcmsCmapRec *)NULL); + } + + pNew->cmapID = cmap; + pNew->dpy = dpy; + pNew->windowID = windowID; + pNew->visual = visual; + pNew->pNext = (XcmsCmapRec *)dpy->cms.clientCmaps; + dpy->cms.clientCmaps = (XPointer)pNew; + dpy->free_funcs->clientCmaps = _XcmsFreeClientCmaps; + + /* + * Note, we don't create the XcmsCCC for pNew->ccc here because + * it may require the use of XGetWindowAttributes (a round trip request) + * to determine the screen. + */ + return(pNew); +} + + +/* + * NAME + * _XcmsCopyCmapRecAndFree + * + * SYNOPSIS + */ +XcmsCmapRec * +_XcmsCopyCmapRecAndFree(dpy, src_cmap, copy_cmap) + Display *dpy; + Colormap src_cmap; + Colormap copy_cmap; +/* + * DESCRIPTION + * Augments Xlib's XCopyColormapAndFree() to copy + * XcmsCmapRecs. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the copy XcmsCmapRec. + * + */ +{ + XcmsCmapRec *pRec_src; + XcmsCmapRec *pRec_copy; + + if ((pRec_src = CmapRecForColormap(dpy, src_cmap)) != NULL) { + pRec_copy =_XcmsAddCmapRec(dpy, copy_cmap, pRec_src->windowID, + pRec_src->visual); + if (pRec_copy != NULL && pRec_src->ccc) { + pRec_copy->ccc = (XcmsCCC)Xcalloc(1, (unsigned) sizeof(XcmsCCCRec)); + memcpy((char *)pRec_copy->ccc, (char *)pRec_src->ccc, + sizeof(XcmsCCCRec)); + } + return(pRec_copy); + } + return((XcmsCmapRec *)NULL); +} + + +/* + * NAME + * _XcmsDeleteCmapRec + * + * SYNOPSIS + */ +void +_XcmsDeleteCmapRec(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Removes and frees the specified XcmsCmapRec structure + * from the linked list of structures. + * + * RETURNS + * void + * + */ +{ + XcmsCmapRec **pPrevPtr; + XcmsCmapRec *pRec; + int scr; + + /* If it is the default cmap for a screen, do not delete it, + * because the server will not actually free it */ + for (scr = ScreenCount(dpy); --scr >= 0; ) { + if (cmap == DefaultColormap(dpy, scr)) + return; + } + + /* search for it in the list */ + pPrevPtr = (XcmsCmapRec **)&dpy->cms.clientCmaps; + while ((pRec = *pPrevPtr) && (pRec->cmapID != cmap)) { + pPrevPtr = &pRec->pNext; + } + + if (pRec) { + if (pRec->ccc) { + XcmsFreeCCC(pRec->ccc); + } + *pPrevPtr = pRec->pNext; + Xfree((char *)pRec); + } +} + + +/* + * NAME + * _XcmsFreeClientCmaps + * + * SYNOPSIS + */ +static void +_XcmsFreeClientCmaps(dpy) + Display *dpy; +/* + * DESCRIPTION + * Frees all XcmsCmapRec structures in the linked list + * and sets dpy->cms.clientCmaps to NULL. + * + * RETURNS + * void + * + */ +{ + XcmsCmapRec *pRecNext, *pRecFree; + + pRecNext = (XcmsCmapRec *)dpy->cms.clientCmaps; + while (pRecNext != NULL) { + pRecFree = pRecNext; + pRecNext = pRecNext->pNext; + if (pRecFree->ccc) { + /* Free the XcmsCCC structure */ + XcmsFreeCCC(pRecFree->ccc); + } + /* Now free the XcmsCmapRec structure */ + Xfree((char *)pRecFree); + } + dpy->cms.clientCmaps = (XPointer)NULL; +} + + + +/************************************************************************ + * * + * PUBLIC INTERFACES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCCCOfColormap + * + * SYNOPSIS + */ +XcmsCCC +XcmsCCCOfColormap(dpy, cmap) + Display *dpy; + Colormap cmap; +/* + * DESCRIPTION + * Finds the XcmsCCC associated with the specified colormap. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the associated XcmsCCC structure. + * + */ +{ + XWindowAttributes windowAttr; + XcmsCmapRec *pRec; + int nScrn = ScreenCount(dpy); + int i; + + if ((pRec = CmapRecForColormap(dpy, cmap)) != NULL) { + if (pRec->ccc) { + /* XcmsCmapRec already has a XcmsCCC */ + return(pRec->ccc); + } + + /* + * The XcmsCmapRec does not have a XcmsCCC yet, so let's create + * one. But first, we need to know the screen associated with + * cmap, so use XGetWindowAttributes() to extract that + * information. Unless, of course there is only one screen!! + */ + if (nScrn == 1) { + /* Assume screenNumber == 0 */ + return(pRec->ccc = XcmsCreateCCC( + dpy, + 0, /* screenNumber */ + pRec->visual, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + )); + } else { + if (XGetWindowAttributes(dpy, pRec->windowID, &windowAttr)) { + for (i = 0; i < nScrn; i++) { + if (ScreenOfDisplay(dpy, i) == windowAttr.screen) { + return(pRec->ccc = XcmsCreateCCC( + dpy, + i, /* screenNumber */ + pRec->visual, + (XcmsColor *)NULL, /* clientWhitePt */ + (XcmsCompressionProc)NULL, /* gamutCompProc */ + (XPointer)NULL, /* gamutCompClientData */ + (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ + (XPointer)NULL /* whitePtAdjClientData */ + )); + } + } + } + } + } + + /* + * No such cmap + */ + return(NULL); +} + +XcmsCCC XcmsSetCCCOfColormap(dpy, cmap, ccc) + Display *dpy; + Colormap cmap; + XcmsCCC ccc; +{ + XcmsCCC prev_ccc = NULL; + XcmsCmapRec *pRec; + + pRec = CmapRecForColormap(dpy, cmap); + if (pRec) { + prev_ccc = pRec->ccc; + pRec->ccc = ccc; + } + return prev_ccc; +} diff --git a/src/xcms/cmsColNm.c b/src/xcms/cmsColNm.c new file mode 100644 index 0000000..e4a9fc9 --- /dev/null +++ b/src/xcms/cmsColNm.c @@ -0,0 +1,1049 @@ +/* $Xorg: cmsColNm.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * XcmsColNm.c + * + * DESCRIPTION + * Source for _XcmsLookupColorName(). + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" +#include <X11/Xos.h> +#include <sys/stat.h> +#include <stdio.h> +#include <ctype.h> +#define XK_LATIN1 +#include <X11/keysymdef.h> + + +/* + * EXTERNS + * External declarations required locally to this package + * that are not already declared in any of the included header + * files (external includes or internal includes). + */ +#ifdef X_NOT_STDC_ENV +extern char *getenv(); +extern void qsort(); +extern char *bsearch(); +#endif +extern XcmsColorSpace **_XcmsDIColorSpaces; +static Status LoadColornameDB(); +void _XcmsCopyISOLatin1Lowered(); + +/* + * LOCAL DEFINES + * #define declarations local to this package. + */ +#ifndef XCMSDB +#define XCMSDB "/usr/lib/X11/Xcms.txt" +#endif + +#ifndef isgraph +# define isgraph(c) (isprint((c)) && !isspace((c))) +#endif + +#ifndef XCMSDB_MAXLINELEN +# define XCMSDB_MAXLINELEN 256 +#endif + +#define FORMAT_VERSION "0.1" +#define START_TOKEN "XCMS_COLORDB_START" +#define END_TOKEN "XCMS_COLORDB_END" +#define DELIM_CHAR '\t' + +#define NOT_VISITED 0x0 +#define VISITED 0x1 +#define CYCLE 0xFFFF +#define XcmsDbInitNone -1 +#define XcmsDbInitFailure 0 +#define XcmsDbInitSuccess 1 + +/* + * LOCAL TYPEDEFS + */ +typedef struct _XcmsPair { + char *first; + char *second; + int flag; +} XcmsPair; + +/* + * LOCAL VARIABLES + */ +static int XcmsColorDbState = XcmsDbInitNone; +static int nEntries; +static char *strings; +static XcmsPair *pairs; +static char whitePtStr[] = "WhitePoint"; + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsColorSpaceOfString + * + * SYNOPSIS + */ +static XcmsColorSpace * +_XcmsColorSpaceOfString(ccc, color_string) + XcmsCCC ccc; + char *color_string; +/* + * DESCRIPTION + * Returns a pointer to the color space structure + * (XcmsColorSpace) associated with the specified color string. + * + * RETURNS + * Pointer to matching XcmsColorSpace structure if found; + * otherwise NULL. + * + * CAVEATS + * + */ +{ + XcmsColorSpace **papColorSpaces; + int n; + char *pchar; + + if ((pchar = strchr(color_string, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - color_string); + + if (ccc == NULL) { + return(NULL); + } + + /* + * First try Device-Independent color spaces + */ + papColorSpaces = _XcmsDIColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && + !((*papColorSpaces)->prefix)[n]) { + return(*papColorSpaces); + } + papColorSpaces++; + } + } + + /* + * Next try Device-Dependent color spaces + */ + papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces; + if (papColorSpaces != NULL) { + while (*papColorSpaces != NULL) { + if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && + !((*papColorSpaces)->prefix)[n]) { + return(*papColorSpaces); + } + papColorSpaces++; + } + } + + return(NULL); +} + + +/* + * NAME + * _XcmsParseColorString + * + * SYNOPSIS + */ +static int +_XcmsParseColorString(ccc, color_string, pColor) + XcmsCCC ccc; + char *color_string; + XcmsColor *pColor; +/* + * DESCRIPTION + * Assuming color_string contains a numerical string color + * specification, attempts to parse a string into an + * XcmsColor structure. + * + * RETURNS + * 0 if failed; otherwise non-zero. + * + * CAVEATS + * A color string containing a numerical color specification + * must be in ISO Latin-1 encoding! + */ +{ + XcmsColorSpace *pColorSpace; + char string_buf[64]; + char *string_lowered; + int len; + int res; + + if (ccc == NULL) { + return(0); + } + + /* + * While copying color_string to string_lowered, convert to lowercase + */ + if ((len = strlen(color_string)) >= sizeof(string_buf)) { + string_lowered = (char *) Xmalloc(len+1); + } else { + string_lowered = string_buf; + } + + _XcmsCopyISOLatin1Lowered(string_lowered, color_string); + + if (*string_lowered == '#') { + if ((pColorSpace = _XcmsColorSpaceOfString(ccc, "rgb:")) != NULL) { + res = (*pColorSpace->parseString)(string_lowered, pColor); + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return res; + } + } + + if ((pColorSpace = _XcmsColorSpaceOfString(ccc, string_lowered)) != NULL) { + res = (*pColorSpace->parseString)(string_lowered, pColor); + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return res; + } + + if (len >= sizeof(string_buf)) Xfree(string_lowered); + return(0); +} + + +/* + * NAME + * FirstCmp - Compare color names of pair recs + * + * SYNOPSIS + */ +static int +FirstCmp(p1, p2) +#ifdef __STDC__ + const void *p1, *p2; +#else + XcmsPair *p1, *p2; +#endif +/* + * DESCRIPTION + * Compares the color names of XcmsColorTuples. + * This routine is public to allow access from qsort???. + * + * RETURNS + * 0 if equal; + * < 0 if first precedes second, + * > 0 if first succeeds second. + * + */ +{ + return(strcmp(((XcmsPair *)p1)->first, ((XcmsPair *)p2)->first)); +} + + + +/* + * NAME + * stringSectionSize - determine memory needed for strings + * + * SYNOPSIS + */ +static void +SetNoVisit() +/* + * DESCRIPTION + * + * RETURNS + * void + * + */ +{ + int i; + XcmsPair *pair = pairs; + + for (i = 0; i < nEntries; i++, pair++) { + if (pair->flag != CYCLE) { + pair->flag = NOT_VISITED; + } + } +} + + + + +/* + * NAME + * field2 - extract two fields + * + * SYNOPSIS + */ +static int +field2(pBuf, delim, p1, p2) + char *pBuf; + char delim; /* in: field delimiter */ + char **p1; /* in/out: pointer to pointer to field 1 */ + char **p2; /* in/out: pointer to pointer to field 2 */ +/* + * DESCRIPTION + * Extracts two fields from a "record". + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure. + * + */ +{ + *p1 = *p2 = NULL; + + /* Find Field 1 */ + while (!isgraph(*pBuf)) { + if ((*pBuf != '\n') || (*pBuf != '\0')) { + return(XcmsFailure); + } + if (isspace(*pBuf) || (*pBuf == delim)) { + pBuf++; + } + } + *p1 = pBuf; + + /* Find end of Field 2 */ + while (isprint(*pBuf) && (*pBuf != delim)) { + pBuf++; + } + if ((*pBuf == '\n') || (*pBuf == '\0')) { + return(XcmsFailure); + } + if ((*pBuf == ' ') || (*pBuf == delim)) { + *pBuf++ = '\0'; /* stuff end of string character */ + } else { + return(XcmsFailure); + } + + /* Find Field 2 */ + while (!isgraph(*pBuf)) { + if ((*pBuf == '\n') || (*pBuf == '\0')) { + return(XcmsFailure); + } + if (isspace(*pBuf) || (*pBuf == delim)) { + pBuf++; + } + } + *p2 = pBuf; + + /* Find end of Field 2 */ + while (isprint(*pBuf) && (*pBuf != delim)) { + pBuf++; + } + if (*pBuf != '\0') { + *pBuf = '\0'; /* stuff end of string character */ + } + + return(XcmsSuccess); +} + + +/* + * NAME + * _XcmsLookupColorName - Lookup DB entry for a color name + * + * SYNOPSIS + */ +static Status +_XcmsLookupColorName(ccc, name, pColor) + XcmsCCC ccc; + char **name; + XcmsColor *pColor; +/* + * DESCRIPTION + * Searches for an entry in the Device-Independent Color Name + * Database for the specified string. + * + * RETURNS + * XcmsFailure if failed to find a matching entry in + * the database. + * XcmsSuccess if succeeded in converting color name to + * XcmsColor. + * _XCMS_NEWNAME if succeeded in converting color string (which + * is a color name to yet another color name. Note + * that the new name is passed back via 'name'. + */ + { + Status retval = 0; + char name_lowered_64[64]; + char *name_lowered; + register int i, j, left, right; + int len; + char *tmpName; + XcmsPair *pair; + + /* + * Check state of Database: + * XcmsDbInitNone + * XcmsDbInitSuccess + * XcmsDbInitFailure + */ + if (XcmsColorDbState == XcmsDbInitFailure) { + return(XcmsFailure); + } + if (XcmsColorDbState == XcmsDbInitNone) { + if (!LoadColornameDB()) { + return(XcmsFailure); + } + } + + SetNoVisit(); + + /* + * While copying name to name_lowered, convert to lowercase + */ + + tmpName = *name; + +Retry: + if ((len = strlen(tmpName)) > 63) { + name_lowered = (char *) Xmalloc(len+1); + } else { + name_lowered = name_lowered_64; + } + + _XcmsCopyISOLatin1Lowered(name_lowered, tmpName); + + /* + * Now, remove spaces. + */ + for (i = 0, j = 0; j < len; j++) { + if (!isspace(name_lowered[j])) { + name_lowered[i++] = name_lowered[j]; + } + } + name_lowered[i] = '\0'; + + left = 0; + right = nEntries - 1; + while (left <= right) { + i = (left + right) >> 1; + pair = &pairs[i]; + j = strcmp(name_lowered, pair->first); + if (j < 0) + right = i - 1; + else if (j > 0) + left = i + 1; + else { + break; + } + } + if (len > 63) Xfree(name_lowered); + + if (left > right) { + if (retval == 2) { + if (*name != tmpName) { + *name = tmpName; + } + return(_XCMS_NEWNAME); + } + return(XcmsFailure); + } + + if (pair->flag == CYCLE) { + return(XcmsFailure); + } + if (pair->flag == VISITED) { + pair->flag = CYCLE; + return(XcmsFailure); + } + + if (_XcmsParseColorString(ccc, pair->second, pColor) == XcmsSuccess) { + /* f2 contains a numerical string specification */ + return(XcmsSuccess); + } else { + /* f2 does not contain a numerical string specification */ + tmpName = pair->second; + pair->flag = VISITED; + retval = 2; + goto Retry; + } +} + + +/* + * NAME + * RemoveSpaces + * + * SYNOPSIS + */ +static int +RemoveSpaces(pString) + char *pString; +/* + * DESCRIPTION + * Removes spaces from string. + * + * RETURNS + * Void + * + */ +{ + int i, count = 0; + char *cptr; + + /* REMOVE SPACES */ + cptr = pString; + for (i = strlen(pString); i; i--, cptr++) { + if (!isspace(*cptr)) { + *pString++ = *cptr; + count++; + } + } + *pString = '\0'; + return(count); +} + + +/* + * NAME + * stringSectionSize - determine memory needed for strings + * + * SYNOPSIS + */ +static int +stringSectionSize(stream, pNumEntries, pSectionSize) + FILE *stream; + int *pNumEntries; + int *pSectionSize; +/* + * DESCRIPTION + * Determines the amount of memory required to store the + * color name strings and also the number of strings. + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure. + * + */ +{ + char buf[XCMSDB_MAXLINELEN]; + char token[XCMSDB_MAXLINELEN]; + char token2[XCMSDB_MAXLINELEN]; + char *pBuf; + char *f1; + char *f2; + int i; + + *pNumEntries = 0; + *pSectionSize = 0; + + /* + * Advance to START_TOKEN + * Anything before is just considered as comments. + */ + + while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { + if ((sscanf(buf, "%s %s", token, token2)) + && (strcmp(token, START_TOKEN) == 0)) { + if (strcmp(token2, FORMAT_VERSION) != 0) { + /* text file not in the right format */ + return(XcmsFailure); + } + break; + } /* else it was just a blank line or comment */ + } + + if (pBuf == NULL) { + return(XcmsFailure); + } + + while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { + if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) { + break; + } + + if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) { + return(XcmsFailure); + } + + (*pNumEntries)++; + + (*pSectionSize) += (i = strlen(f1)) + 1; + for (; i; i--, f1++) { + /* REMOVE SPACES FROM COUNT */ + if (isspace(*f1)) { + (*pSectionSize)--; + } + } + + (*pSectionSize) += (i = strlen(f2)) + 1; + for (; i; i--, f2++) { + /* REMOVE SPACES FROM COUNT */ + if (isspace(*f2)) { + (*pSectionSize)--; + } + } + + } + + return(XcmsSuccess); +} + + +/* + * NAME + * ReadColornameDB - Read the Color Name Database + * + * SYNOPSIS + */ +static Status +ReadColornameDB(stream, pRec, pString) + FILE *stream; + XcmsPair *pRec; + char *pString; +/* + * DESCRIPTION + * Loads the Color Name Database from a text file. + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure. + * + */ +{ + char buf[XCMSDB_MAXLINELEN]; + char token[XCMSDB_MAXLINELEN]; + char token2[XCMSDB_MAXLINELEN]; + char *f1; + char *f2; + char *pBuf; + + /* + * Advance to START_TOKEN + * Anything before is just considered as comments. + */ + + while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { + if ((sscanf(buf, "%s %s", token, token2)) + && (strcmp(token, START_TOKEN) == 0)) { + if (strcmp(token2, FORMAT_VERSION) != 0) { + /* text file not in the right format */ + return(XcmsFailure); + } + break; + } /* else it was just a blank line or comment */ + } + + if (pBuf == NULL) { + return(XcmsFailure); + } + + /* + * Process lines between START_TOKEN to END_TOKEN + */ + + while ((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { + if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) { + /* + * Found END_TOKEN so break out of for loop + */ + break; + } + + /* + * Get pairs + */ + if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) { + /* Invalid line */ + continue; + } + + /* + * Add strings + */ + + /* Left String */ + pRec->first = pString; + _XcmsCopyISOLatin1Lowered(pString, f1); + pString += (1 + RemoveSpaces(pString)); + pRec->second = pString; + /* Right String */ + _XcmsCopyISOLatin1Lowered(pString, f2); + pString += RemoveSpaces(pString) + 1; + pRec++; + + } + + return(XcmsSuccess); +} + + +/* + * NAME + * LoadColornameDB - Load the Color Name Database + * + * SYNOPSIS + */ +static Status +LoadColornameDB() +/* + * DESCRIPTION + * Loads the Color Name Database from a text file. + * + * RETURNS + * XcmsSuccess if succeeded, otherwise XcmsFailure. + * + */ +{ + int size; + FILE *stream; + char *pathname; + struct stat txt; + int length; + + /* use and name of this env var is not part of the standard */ + /* implementation-dependent feature */ + if ((pathname = getenv("XCMSDB")) == NULL) { + pathname = XCMSDB; + } + + length = strlen(pathname); + if ((length == 0) || (length >= (BUFSIZ - 5))){ + XcmsColorDbState = XcmsDbInitFailure; + return(XcmsFailure); + } + + if (stat(pathname, &txt)) { + /* can't stat file */ + XcmsColorDbState = XcmsDbInitFailure; + return(XcmsFailure); + } + + if ((stream = _XFopenFile (pathname, "r")) == NULL) { + return(XcmsFailure); + } + + stringSectionSize(stream, &nEntries, &size); + rewind(stream); + + strings = (char *) Xmalloc(size); + pairs = (XcmsPair *)Xcalloc(nEntries, sizeof(XcmsPair)); + + ReadColornameDB(stream, pairs, strings); + (void) fclose(stream); + + /* + * sort the pair recs + */ + qsort((char *)pairs, nEntries, sizeof(XcmsPair), FirstCmp); + + XcmsColorDbState = XcmsDbInitSuccess; + return(XcmsSuccess); +} + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsCopyISOLatin1Lowered + * + * SYNOPSIS + */ +void +_XcmsCopyISOLatin1Lowered(dst, src) + char *dst, *src; +/* + * DESCRIPTION + * ISO Latin-1 case conversion routine + * Identical to XmuCopyISOLatin1Lowered() but provided here + * to eliminate need to link with libXmu.a. + * + * IMPLEMENTORS NOTE: + * This routine is also used in XcmsFormatOfPrefix. + * + * RETURNS + * Void + * + */ +{ + register unsigned char *dest, *source; + + for (dest = (unsigned char *)dst, source = (unsigned char *)src; + *source; + source++, dest++) + { + if ((*source >= XK_A) && (*source <= XK_Z)) + *dest = *source + (XK_a - XK_A); + else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis)) + *dest = *source + (XK_agrave - XK_Agrave); + else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn)) + *dest = *source + (XK_oslash - XK_Ooblique); + else + *dest = *source; + } + *dest = '\0'; +} + + +/* + * NAME + * _XcmsResolveColorString - + * + * SYNOPSIS + */ +#if NeedFunctionPrototypes +Status +_XcmsResolveColorString ( + XcmsCCC ccc, + _Xconst char **color_string, + XcmsColor *pColor_exact_return, + XcmsColorFormat result_format) +#else +Status +_XcmsResolveColorString(ccc, color_string, pColor_exact_return, result_format) + XcmsCCC ccc; + char **color_string; + XcmsColor *pColor_exact_return; + XcmsColorFormat result_format; +#endif +/* + * DESCRIPTION + * The XcmsLookupColor function finds the color specification + * associated with a color name in the Device-Independent Color + * Name Database. + * RETURNS + * XcmsFailure if failed to convert valid color string. + * XcmsSuccess if succeeded in converting color string to + * XcmsColor. + * _XCMS_NEWNAME if failed to parse the string or find it in + * the database, or if succeeded in looking it up and + * found another name which is not in the database. + * Note that the new name is returned in color_string. + * + * This function returns both the color specification found in the + * database (db specification) and the color specification for the + * color displayable by the specified screen (screen + * specification). The calling routine sets the format for these + * returned specifications in the XcmsColor format component. + * If XcmsUndefinedFormat, the specification is returned in the + * format used to store the color in the database. + */ +{ + XcmsColor dbWhitePt; /* whitePt associated with pColor_exact_return*/ + /* the screen's white point */ + XcmsColor *pClientWhitePt; + int retval; + char *strptr = whitePtStr; + +/* + * 0. Check for invalid arguments. + */ + if (ccc == NULL || (*color_string)[0] == '\0' || pColor_exact_return == NULL) { + return(XcmsFailure); + } + +/* + * 1. First attempt to parse the string + * If successful, then convert the specification to the target format + * and return. + */ + if (_XcmsParseColorString(ccc, *color_string, pColor_exact_return) + == 1) { + if (result_format != XcmsUndefinedFormat + && pColor_exact_return->format != result_format) { + /* need to be converted to the target format */ + return(XcmsConvertColors(ccc, pColor_exact_return, 1, + result_format, (Bool *)NULL)); + } else { + return(XcmsSuccess); + } + } + +/* + * 2. Attempt to find it in the DI Color Name Database + */ + + /* + * a. Convert String into a XcmsColor structure + * Attempt to extract the specification for color_string from the + * DI Database (pColor_exact_return). If the DI Database does not + * have this entry, then return failure. + */ + retval = _XcmsLookupColorName(ccc, color_string, pColor_exact_return); + + if (retval != XcmsSuccess) { + /* color_string replaced with a color name, or not found */ + return(_XCMS_NEWNAME); + } + + if (pColor_exact_return->format == XcmsUndefinedFormat) { + return(XcmsFailure); + } + + /* + * b. If result_format not defined, then assume target format + * is the exact format. + */ + if (result_format == XcmsUndefinedFormat) { + result_format = pColor_exact_return->format; + } + + if ((ClientWhitePointOfCCC(ccc))->format == XcmsUndefinedFormat) { + pClientWhitePt = ScreenWhitePointOfCCC(ccc); + } else { + pClientWhitePt = ClientWhitePointOfCCC(ccc); + } + + /* + * c. Convert to the target format, making adjustments for white + * point differences as necessary. + */ + if (XCMS_DD_ID(pColor_exact_return->format)) { + /* + * The spec format is Device-Dependent, therefore assume the + * its white point is the Screen White Point. + */ + if (XCMS_DD_ID(result_format)) { + /* + * Target format is Device-Dependent + * Therefore, DD --> DD conversion + */ + return(_XcmsDDConvertColors(ccc, pColor_exact_return, + 1, result_format, (Bool *) NULL)); + } else { + /* + * Target format is Device-Independent + * Therefore, DD --> DI conversion + */ + if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, + pClientWhitePt, ScreenWhitePointOfCCC(ccc))) { + return((*ccc->whitePtAdjProc)(ccc, ScreenWhitePointOfCCC(ccc), + pClientWhitePt, result_format, + pColor_exact_return, 1, (Bool *) NULL)); + } else { + if (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, + XcmsCIEXYZFormat, (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + return(_XcmsDIConvertColors(ccc, pColor_exact_return, + pClientWhitePt, 1, result_format)); + } + } + } else { + /* + * The spec format is Device-Independent, therefore attempt + * to find a database white point. + * + * If the Database does not have a white point, then assume the + * database white point is the same as the Screen White Point. + */ + + if (_XcmsLookupColorName(ccc, &strptr, &dbWhitePt) != 1) { + memcpy((char *)&dbWhitePt, + (char *)&ccc->pPerScrnInfo->screenWhitePt, + sizeof(XcmsColor)); + } + if (XCMS_DD_ID(result_format)) { + /* + * Target format is Device-Dependent + * Therefore, DI --> DD conversion + */ + if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, + &dbWhitePt, ScreenWhitePointOfCCC(ccc))) { + return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, + ScreenWhitePointOfCCC(ccc), result_format, + pColor_exact_return, 1, (Bool *)NULL)); + } else { + if (pColor_exact_return->format != XcmsCIEXYZFormat) { + if (_XcmsDIConvertColors(ccc, pColor_exact_return, + &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) { + return(XcmsFailure); + } + } + return (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, + result_format, (Bool *)NULL)); + } + } else { + /* + * Target format is Device-Independent + * Therefore, DI --> DI conversion + */ + if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, + &dbWhitePt, pClientWhitePt)) { + /* + * The calling routine wants to resolve this color + * in terms if it's white point (i.e. Client White Point). + * Therefore, apply white adjustment for the displacement + * between dbWhitePt to clientWhitePt. + */ + return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, + pClientWhitePt, result_format, + pColor_exact_return, 1, (Bool *)NULL)); + } else if (_XcmsEqualWhitePts(ccc, + &dbWhitePt, pClientWhitePt)) { + /* + * Can use either dbWhitePt or pClientWhitePt to + * convert to the result_format. + */ + if (pColor_exact_return->format == result_format) { + return(XcmsSuccess); + } else { + return (_XcmsDIConvertColors(ccc, pColor_exact_return, + &dbWhitePt, 1, result_format)); + } + } else { + /* + * Need to convert to a white point independent color + * space (let's choose CIEXYZ) then convert to the + * target color space. Why? Lets assume that + * pColor_exact_return->format and result format + * are white point dependent format (e.g., CIELUV, CIELAB, + * TekHVC ... same or any combination). If so, we'll + * need to convert the color with dbWhitePt to an absolute + * spec (i.e. non-white point dependent) then convert that + * absolute value with clientWhitePt to the result_format. + */ + if (pColor_exact_return->format != XcmsCIEXYZFormat) { + if (_XcmsDIConvertColors(ccc, pColor_exact_return, + &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) { + return(XcmsFailure); + } + } + if (result_format == XcmsCIEXYZFormat) { + return(XcmsSuccess); + } else { + return(_XcmsDIConvertColors(ccc, pColor_exact_return, + pClientWhitePt, 1, result_format)); + } + } + } + } +} diff --git a/src/xcms/cmsGlobls.c b/src/xcms/cmsGlobls.c new file mode 100644 index 0000000..deeea98 --- /dev/null +++ b/src/xcms/cmsGlobls.c @@ -0,0 +1,160 @@ +/*$Xorg: cmsGlobls.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsGlobls.c + * + * DESCRIPTION + * Source file containing Xcms globals + * + * + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + * External declarations required locally to this package + * that are not already declared in any of the included header + * files (external includes or internal includes). + */ +extern XcmsFunctionSet XcmsLinearRGBFunctionSet; +#ifdef GRAY +extern XcmsFunctionSet XcmsGrayFunctionSet; +#endif /* GRAY */ + +/* UNDEFINED Color Space */ +extern XcmsColorSpace XcmsUNDEFINEDColorSpace; + +/* CIE XYZ Color Space */ +extern XcmsColorSpace XcmsCIEXYZColorSpace; + +/* CIE uvY Color Space */ +extern XcmsColorSpace XcmsCIEuvYColorSpace; + +/* CIE xyY Color Space */ +extern XcmsColorSpace XcmsCIExyYColorSpace; + +/* CIE Lab Color Space */ +extern XcmsColorSpace XcmsCIELabColorSpace; + +/* CIE Luv Color Space */ +extern XcmsColorSpace XcmsCIELuvColorSpace; + +/* TekHVC Color Space */ +extern XcmsColorSpace XcmsTekHVCColorSpace; + +/* Device Dependent Color Space Structures */ +extern XcmsColorSpace XcmsRGBiColorSpace; +extern XcmsColorSpace XcmsRGBColorSpace; + + +/* + * GLOBALS + * Variables declared in this package that are allowed + * to be used globally. + */ + + /* + * Initial array of Device Independent Color Spaces + */ +XcmsColorSpace *_XcmsDIColorSpacesInit[] = { + &XcmsCIEXYZColorSpace, + &XcmsCIEuvYColorSpace, + &XcmsCIExyYColorSpace, + &XcmsCIELabColorSpace, + &XcmsCIELuvColorSpace, + &XcmsTekHVCColorSpace, + &XcmsUNDEFINEDColorSpace, + NULL +}; + /* + * Pointer to the array of pointers to XcmsColorSpace structures for + * Device-Independent Color Spaces that are currently accessible by + * the color management system. End of list is indicated by a NULL pointer. + */ +XcmsColorSpace **_XcmsDIColorSpaces = _XcmsDIColorSpacesInit; + + /* + * Initial array of Device Dependent Color Spaces + */ +XcmsColorSpace *_XcmsDDColorSpacesInit[] = { + &XcmsRGBColorSpace, + &XcmsRGBiColorSpace, + NULL +}; + /* + * Pointer to the array of pointers to XcmsColorSpace structures for + * Device-Dependent Color Spaces that are currently accessible by + * the color management system. End of list is indicated by a NULL pointer. + */ +XcmsColorSpace **_XcmsDDColorSpaces = &_XcmsDDColorSpacesInit[0]; + + /* + * Initial array of Screen Color Characterization Function Sets + */ +XcmsFunctionSet *_XcmsSCCFuncSetsInit[] = { + &XcmsLinearRGBFunctionSet, +#ifdef GRAY + &XcmsGrayFunctionSet, +#endif /* GRAY */ + NULL}; + /* + * Pointer to the array of pointers to XcmsSCCFuncSet structures + * (Screen Color Characterization Function Sets) that are currently + * accessible by the color management system. End of list is + * indicated by a NULL pointer. + */ +XcmsFunctionSet **_XcmsSCCFuncSets = _XcmsSCCFuncSetsInit; + + /* + * X Consortium Registered Device-Independent Color Spaces + * Note that prefix must be in lowercase. + */ +char _XcmsCIEXYZ_prefix[] = "ciexyz"; +char _XcmsCIEuvY_prefix[] = "cieuvy"; +char _XcmsCIExyY_prefix[] = "ciexyy"; +char _XcmsCIELab_prefix[] = "cielab"; +char _XcmsCIELuv_prefix[] = "cieluv"; +char _XcmsTekHVC_prefix[] = "tekhvc"; + /* + * Registered Device-Dependent Color Spaces + */ +char _XcmsRGBi_prefix[] = "rgbi"; +char _XcmsRGB_prefix[] = "rgb"; + +XcmsRegColorSpaceEntry _XcmsRegColorSpaces[] = { + _XcmsCIEXYZ_prefix, XcmsCIEXYZFormat, + _XcmsCIEuvY_prefix, XcmsCIEuvYFormat, + _XcmsCIExyY_prefix, XcmsCIExyYFormat, + _XcmsCIELab_prefix, XcmsCIELabFormat, + _XcmsCIELuv_prefix, XcmsCIELuvFormat, + _XcmsTekHVC_prefix, XcmsTekHVCFormat, + _XcmsRGB_prefix, XcmsRGBFormat, + _XcmsRGBi_prefix, XcmsRGBiFormat, + NULL, 0 +}; diff --git a/src/xcms/cmsInt.c b/src/xcms/cmsInt.c new file mode 100644 index 0000000..b70e2c0 --- /dev/null +++ b/src/xcms/cmsInt.c @@ -0,0 +1,420 @@ +/* $Xorg: cmsInt.c,v 1.4 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsInt.c - Xcms API utility routines + * + * DESCRIPTION + * Xcms Application Program Interface (API) utility + * routines for hanging information directly onto + * the Display structure. + * + * + */ + +/* #define NEED_EVENTS */ +#include <stdio.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +#ifndef XCMSCOMPPROC +# define XCMSCOMPPROC XcmsTekHVCClipC +#endif + +/* + * EXTERNS + */ +extern XcmsColorSpace **_XcmsDIColorSpaces; +extern XcmsFunctionSet **_XcmsSCCFuncSets; + +static void _XcmsFreeDefaultCCCs(); + +/* + * GLOBALS + */ + + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * _XcmsCopyPointerArray + * + * SYNOPSIS + */ +XPointer * +_XcmsCopyPointerArray(pap) + XPointer *pap; +/* + * DESCRIPTION + * Copies an array of NULL terminated pointers. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the copy. + * + */ +{ + XPointer *newArray; + char **tmp; + int n; + + for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++); + n++; /* add 1 to include the NULL pointer */ + + if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) { + memcpy((char *)newArray, (char *)pap, + (unsigned)(n * sizeof(XPointer))); + } + return((XPointer *)newArray); +} + +/* + * NAME + * _XcmsFreePointerArray + * + * SYNOPSIS + */ +void +_XcmsFreePointerArray(pap) + XPointer *pap; +/* + * DESCRIPTION + * Frees an array of NULL terminated pointers. + * + * RETURNS + * void + * + */ +{ + Xfree(pap); +} + +/* + * NAME + * _XcmsPushPointerArray + * + * SYNOPSIS + */ +XPointer * +_XcmsPushPointerArray(pap, p, papNoFree) + XPointer *pap; + XPointer p; + XPointer *papNoFree; +/* + * DESCRIPTION + * Places the specified pointer at the head of an array of NULL + * terminated pointers. + * + * RETURNS + * Returns NULL if failed; otherwise the address to + * the head of the array. + * + */ +{ + XPointer *newArray; + char **tmp; + int n; + + for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++); + + /* add 2: 1 for the new pointer and another for the NULL pointer */ + n += 2; + + if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) { + memcpy((char *)(newArray+1),(char *)pap, + (unsigned)((n-1) * sizeof(XPointer))); + *newArray = p; + } + if (pap != papNoFree) { + _XcmsFreePointerArray(pap); + } + return((XPointer *)newArray); +} + +/* + * NAME + * _XcmsInitDefaultCCCs + * + * SYNOPSIS + */ +int +_XcmsInitDefaultCCCs(dpy) + Display *dpy; +/* + * DESCRIPTION + * Initializes the Xcms per Display Info structure + * (XcmsPerDpyInfo). + * + * RETURNS + * Returns 0 if failed; otherwise non-zero. + * + */ +{ + int nScrn = ScreenCount(dpy); + int i; + XcmsCCC ccc; + + if (nScrn <= 0) { + return(0); + } + + /* + * Create an array of XcmsCCC structures, one for each screen. + * They serve as the screen's default CCC. + */ + if (!(ccc = (XcmsCCC) + Xcalloc((unsigned)nScrn, (unsigned) sizeof(XcmsCCCRec)))) { + return(0); + } + dpy->cms.defaultCCCs = (XPointer)ccc; + dpy->free_funcs->defaultCCCs = _XcmsFreeDefaultCCCs; + + for (i = 0; i < nScrn; i++, ccc++) { + ccc->dpy = dpy; + ccc->screenNumber = i; + ccc->visual = DefaultVisual(dpy, i); + /* + * Used calloc to allocate memory so: + * ccc->clientWhitePt->format == XcmsUndefinedFormat + * ccc->gamutCompProc == NULL + * ccc->whitePtAdjProc == NULL + * ccc->pPerScrnInfo = NULL + * + * Don't need to create XcmsPerScrnInfo and its functionSet and + * pScreenData components until the default CCC is accessed. + * Note that the XcmsDefaultCCC routine calls _XcmsInitScrnInto + * to do this. + */ + ccc->gamutCompProc = XCMSCOMPPROC; + } + + return(1); +} + + +/* + * NAME + * _XcmsFreeDefaultCCCs - Free Default CCCs and its PerScrnInfo + * + * SYNOPSIS + */ +static void +_XcmsFreeDefaultCCCs(dpy) + Display *dpy; +/* + * DESCRIPTION + * This routine frees the default XcmsCCC's associated with + * each screen and its associated substructures as neccessary. + * + * RETURNS + * void + * + * + */ +{ + int nScrn = ScreenCount(dpy); + XcmsCCC ccc; + int i; + + /* + * Free Screen data in each DefaultCCC + * Do not use XcmsFreeCCC here because it will not free + * DefaultCCC's. + */ + ccc = (XcmsCCC)dpy->cms.defaultCCCs; + for (i = nScrn; i--; ccc++) { + /* + * Check if XcmsPerScrnInfo exists. + * + * This is the only place where XcmsPerScrnInfo structures + * are freed since there is only one allocated per Screen. + * It just so happens that we place its reference in the + * default CCC. + */ + if (ccc->pPerScrnInfo) { + /* Check if SCCData exists */ + if (ccc->pPerScrnInfo->state != XcmsInitNone + && ccc->pPerScrnInfo->screenData) { + (*((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->screenFreeProc) + (ccc->pPerScrnInfo->screenData); + } + Xfree(ccc->pPerScrnInfo); + } + } + + /* + * Free the array of XcmsCCC structures + */ + Xfree(dpy->cms.defaultCCCs); + dpy->cms.defaultCCCs = (XPointer)NULL; +} + + + +/* + * NAME + * _XcmsInitScrnInfo + * + * SYNOPSIS + */ +int +_XcmsInitScrnInfo(dpy, screenNumber) + register Display *dpy; + int screenNumber; +/* + * DESCRIPTION + * Given a display and screen number, this routine attempts + * to initialize the Xcms per Screen Info structure + * (XcmsPerScrnInfo). + * + * RETURNS + * Returns zero if initialization failed; non-zero otherwise. + */ +{ + XcmsFunctionSet **papSCCFuncSet = _XcmsSCCFuncSets; + XcmsCCC defaultccc; + + /* + * Check if the XcmsCCC's for each screen has been created. + * Really dont need to be created until some routine uses the Xcms + * API routines. + */ + if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) { + if (!_XcmsInitDefaultCCCs(dpy)) { + return(0); + } + } + + defaultccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber; + + /* + * For each SCCFuncSet, try its pInitScrnFunc. + * If the function succeeds, then we got it! + */ + + if (!defaultccc->pPerScrnInfo) { + /* + * This is one of two places where XcmsPerScrnInfo structures + * are allocated. There is one allocated per Screen that is + * shared among visuals that do not have specific intensity + * tables. Other XcmsPerScrnInfo structures are created + * for the latter (see XcmsCreateCCC). The ones created + * here are referenced by the default CCC. + */ + if (!(defaultccc->pPerScrnInfo = (XcmsPerScrnInfo *) + Xcalloc(1, (unsigned) sizeof(XcmsPerScrnInfo)))) { + return(0); + } + defaultccc->pPerScrnInfo->state = XcmsInitNone; + } + + while (*papSCCFuncSet != NULL) { + if ((*(*papSCCFuncSet)->screenInitProc)(dpy, screenNumber, + defaultccc->pPerScrnInfo)) { + defaultccc->pPerScrnInfo->state = XcmsInitSuccess; + return(1); + } + papSCCFuncSet++; + } + + /* + * Use Default SCCData + */ + return(_XcmsLRGB_InitScrnDefault(dpy, screenNumber, defaultccc->pPerScrnInfo)); +} + + +/* + * NAME + * _XcmsFreeIntensityMaps + * + * SYNOPSIS + */ +void +_XcmsFreeIntensityMaps(dpy) + Display *dpy; +/* + * DESCRIPTION + * Frees all XcmsIntensityMap structures in the linked list + * and sets dpy->cms.perVisualIntensityMaps to NULL. + * + * RETURNS + * void + * + */ +{ + XcmsIntensityMap *pNext, *pFree; + + pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; + while (pNext != NULL) { + pFree = pNext; + pNext = pNext->pNext; + (*pFree->pFreeScreenData)(pFree->screenData); + /* Now free the XcmsIntensityMap structure */ + Xfree(pFree); + } + dpy->cms.perVisualIntensityMaps = (XPointer)NULL; +} + + +/* + * NAME + * _XcmsGetIntensityMap + * + * SYNOPSIS + */ +XcmsIntensityMap * +_XcmsGetIntensityMap(dpy, visual) + Display *dpy; + Visual *visual; +/* + * DESCRIPTION + * Attempts to return a per-Visual intensity map. + * + * RETURNS + * Pointer to the XcmsIntensityMap structure if found; + * otherwise NULL + * + */ +{ + VisualID targetID = visual->visualid; + XcmsIntensityMap *pNext; + + pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; + while (pNext != NULL) { + if (targetID == pNext->visualID) { + return(pNext); + } + pNext = pNext->pNext; + } + return((XcmsIntensityMap *)NULL); +} diff --git a/src/xcms/cmsLkCol.c b/src/xcms/cmsLkCol.c new file mode 100644 index 0000000..eb9669f --- /dev/null +++ b/src/xcms/cmsLkCol.c @@ -0,0 +1,213 @@ +/* $Xorg: cmsLkCol.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * XcmsLkCol.c + * + * DESCRIPTION + * Source for XcmsLookupColor + * + * + */ + +#define NEED_REPLIES +#include <stdio.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * EXTERNS + */ +extern void _XColor_to_XcmsRGB(); +extern void _XcmsRGB_to_XColor(); +extern void _XcmsResolveColor(); +extern void _XcmsUnresolveColor(); +#ifdef X_NOT_STDC_ENV +extern char *getenv(); +#endif + +/* + * NAME + * XcmsLookupColor - + * + * SYNOPSIS + */ +#if NeedFunctionPrototypes +Status +XcmsLookupColor ( + Display *dpy, + Colormap cmap, + _Xconst char *colorname, + XcmsColor *pColor_exact_return, + XcmsColor *pColor_scrn_return, + XcmsColorFormat result_format) +#else +Status +XcmsLookupColor(dpy, cmap, colorname, pColor_exact_return, pColor_scrn_return, + result_format) + Display *dpy; + Colormap cmap; + char *colorname; + XcmsColor *pColor_exact_return; + XcmsColor *pColor_scrn_return; + XcmsColorFormat result_format; +#endif +/* + * DESCRIPTION + * The XcmsLookupColor function finds the color specification + * associated with a color name in the Device-Independent Color + * Name Database. + * RETURNS + * This function returns both the color specification found in the + * database (db specification) and the color specification for the + * color displayable by the specified screen (screen + * specification). The calling routine sets the format for these + * returned specifications in the XcmsColor format component. + * If XcmsUndefinedFormat, the specification is returned in the + * format used to store the color in the database. + */ +{ + Status retval1 = XcmsSuccess; + Status retval2 = XcmsSuccess; + XcmsCCC ccc; + register int n; + xLookupColorReply reply; + register xLookupColorReq *req; + XColor def, scr; + +/* + * 0. Check for invalid arguments. + */ + if (dpy == NULL || colorname[0] == '\0' || pColor_scrn_return == 0 + || pColor_exact_return == NULL) { + return(XcmsFailure); + } + + if ((ccc = XcmsCCCOfColormap(dpy, cmap)) == (XcmsCCC)NULL) { + return(XcmsFailure); + } + +/* + * 1. Convert string to a XcmsColor + */ + if ((retval1 = _XcmsResolveColorString(ccc, &colorname, + pColor_exact_return, result_format)) == XcmsFailure) { + return(XcmsFailure); + } + if (retval1 == _XCMS_NEWNAME) { + goto PassToServer; + } + +/* + * 2. pColor_scrn_return + * Assume the pColor_exact_return has already been adjusted to + * the Client White Point. + * + */ + /* + * Convert to RGB, adjusting for white point differences if necessary. + */ + memcpy((char *)pColor_scrn_return, (char *)pColor_exact_return, + sizeof(XcmsColor)); + if (pColor_scrn_return->format == XcmsRGBFormat) { + retval2 = XcmsSuccess; + } else if ((retval2 = XcmsConvertColors(ccc, pColor_scrn_return, 1, + XcmsRGBFormat, (Bool *)NULL)) == XcmsFailure) { + return(XcmsFailure); + } + + /* + * Then, convert XcmsColor structure to the target specification + * format. Note that we must use NULL instead of passing + * pCompressed. + */ + + if (result_format == XcmsUndefinedFormat) { + result_format = pColor_exact_return->format; + } + if (result_format == XcmsRGBFormat) { + _XcmsUnresolveColor(ccc, pColor_scrn_return); + } else { + _XcmsResolveColor(ccc, pColor_scrn_return); + if (XcmsConvertColors(ccc, pColor_scrn_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + } + + return(retval1 > retval2 ? retval1 : retval2); + +PassToServer: + /* + * Xcms and i18n methods failed, so lets pass it to the server + * for parsing. + */ + + LockDisplay(dpy); + GetReq (LookupColor, req); + req->cmap = cmap; + req->nbytes = n = strlen(colorname); + req->length += (n + 3) >> 2; + Data (dpy, colorname, (long)n); + if (!_XReply (dpy, (xReply *) &reply, 0, xTrue)) { + UnlockDisplay(dpy); + SyncHandle(); + return (XcmsFailure); + } + def.red = reply.exactRed; + def.green = reply.exactGreen; + def.blue = reply.exactBlue; + + scr.red = reply.screenRed; + scr.green = reply.screenGreen; + scr.blue = reply.screenBlue; + + UnlockDisplay(dpy); + SyncHandle(); + + _XColor_to_XcmsRGB(ccc, &def, pColor_exact_return, 1); + _XColor_to_XcmsRGB(ccc, &scr, pColor_scrn_return, 1); + + /* + * Then, convert XcmsColor structure to the target specification + * format. Note that we must use NULL instead of passing + * pCompressed. + */ + + if (result_format != XcmsRGBFormat + && result_format != XcmsUndefinedFormat) { + if (XcmsConvertColors(ccc, pColor_exact_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + if (XcmsConvertColors(ccc, pColor_scrn_return, 1, result_format, + (Bool *) NULL) == XcmsFailure) { + return(XcmsFailure); + } + } + + return(XcmsSuccess); +} diff --git a/src/xcms/cmsMath.c b/src/xcms/cmsMath.c new file mode 100644 index 0000000..fd09cec --- /dev/null +++ b/src/xcms/cmsMath.c @@ -0,0 +1,138 @@ +/* $Xorg: cmsMath.c,v 1.4 2001/02/09 02:03:39 xorgcvs Exp $ */ + +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Stephen Gildea, MIT X Consortium, January 1991 + */ + +#include "Xlibint.h" +#include "Xcmsint.h" + +#if !defined(X_NOT_STDC_ENV) && (defined(__STDC__) || !(defined(sun) || (defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV)))) +#include <float.h> +#endif +#ifndef DBL_EPSILON +#define DBL_EPSILON 1e-6 +#endif + +#ifdef _X_ROOT_STATS +int cbrt_loopcount; +int sqrt_loopcount; +#endif + +/* Newton's Method: x_n+1 = x_n - ( f(x_n) / f'(x_n) ) */ + + +/* for cube roots, x^3 - a = 0, x_new = x - 1/3 (x - a/x^2) */ + +double +_XcmsCubeRoot(a) + double a; +{ + register double abs_a, cur_guess, delta; + +#ifdef DEBUG + printf("_XcmsCubeRoot passed in %g\n", a); +#endif +#ifdef _X_ROOT_STATS + cbrt_loopcount = 0; +#endif + if (a == 0.) + return 0.; + + abs_a = a<0. ? -a : a; /* convert to positive to speed loop tests */ + + /* arbitrary first guess */ + if (abs_a > 1.) + cur_guess = abs_a/8.; + else + cur_guess = abs_a*8.; + + do { +#ifdef _X_ROOT_STATS + cbrt_loopcount++; +#endif + delta = (cur_guess - abs_a/(cur_guess*cur_guess))/3.; + cur_guess -= delta; + if (delta < 0.) delta = -delta; + } while (delta >= cur_guess*DBL_EPSILON); + + if (a < 0.) + cur_guess = -cur_guess; + +#ifdef DEBUG + printf("_XcmsCubeRoot returning %g\n", cur_guess); +#endif + return cur_guess; +} + + + +/* for square roots, x^2 - a = 0, x_new = x - 1/2 (x - a/x) */ + +double +_XcmsSquareRoot(a) + double a; +{ + register double cur_guess, delta; + +#ifdef DEBUG + printf("_XcmsSquareRoot passed in %g\n", a); +#endif +#ifdef _X_ROOT_STATS + sqrt_loopcount = 0; +#endif + if (a == 0.) + return 0.; + + if (a < 0.) { + /* errno = EDOM; */ + return 0.; + } + + /* arbitrary first guess */ + if (a > 1.) + cur_guess = a/4.; + else + cur_guess = a*4.; + + do { +#ifdef _X_ROOT_STATS + sqrt_loopcount++; +#endif + delta = (cur_guess - a/cur_guess)/2.; + cur_guess -= delta; + if (delta < 0.) delta = -delta; + } while (delta >= cur_guess*DBL_EPSILON); + +#ifdef DEBUG + printf("_XcmsSquareRoot returning %g\n", cur_guess); +#endif + return cur_guess; +} + diff --git a/src/xcms/cmsProp.c b/src/xcms/cmsProp.c new file mode 100644 index 0000000..28d7a88 --- /dev/null +++ b/src/xcms/cmsProp.c @@ -0,0 +1,143 @@ +/* $Xorg: cmsProp.c,v 1.3 2000/08/17 19:45:10 cpqbld Exp $ */ + +/* + * + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * XcmsProp.c + * + * DESCRIPTION + * This utility routines for manipulating properties. + * + */ + +#include <X11/Xatom.h> +#include "Xlibint.h" +#include "Xcmsint.h" + + +/************************************************************************ + * * + * API PRIVATE ROUTINES * + * * + ************************************************************************/ + + +/* + * NAME + * _XcmsGetElement -- get an element value from the property passed + * + * SYNOPSIS + */ +unsigned long +_XcmsGetElement (format, pValue, pCount) + int format; + char **pValue; + unsigned long *pCount; +/* + * DESCRIPTION + * Get the next element from the property and return it. + * Also increment the pointer the amount needed. + * + * Returns + * unsigned long + */ +{ + unsigned long value; + + switch (format) { + case 32: + value = *((unsigned long *)(*pValue)) & 0xFFFFFFFF; + *pValue += sizeof(unsigned long); + *pCount -= 1; + break; + case 16: + value = *((unsigned short *)(*pValue)); + *pValue += sizeof(unsigned short); + *pCount -= 1; + break; + case 8: + value = *((unsigned char *) (*pValue)); + *pValue += 1; + *pCount -= 1; + break; + default: + value = 0; + break; + } + return(value); +} + + +/* + * NAME + * _XcmsGetProperty -- Determine the existance of a property + * + * SYNOPSIS + */ +int +_XcmsGetProperty (pDpy, w, property, pFormat, pNItems, pNBytes, pValue) + Display *pDpy; + Window w; + Atom property; + int *pFormat; + unsigned long *pNItems; + unsigned long *pNBytes; + char **pValue; +/* + * DESCRIPTION + * + * Returns + * 0 if property does not exist. + * 1 if property exists. + */ +{ + char *prop_ret; + int format_ret; + long len = 6516; + unsigned long nitems_ret, after_ret; + Atom atom_ret; + + while (XGetWindowProperty (pDpy, w, property, 0, len, False, + XA_INTEGER, &atom_ret, &format_ret, + &nitems_ret, &after_ret, + (unsigned char **)&prop_ret)) { + if (after_ret > 0) { + len += nitems_ret * (format_ret >> 3); + XFree (prop_ret); + } else { + break; + } + } + if (format_ret == 0 || nitems_ret == 0) { + /* the property does not exist or is of an unexpected type */ + return(XcmsFailure); + } + + *pFormat = format_ret; + *pNItems = nitems_ret; + *pNBytes = nitems_ret * (format_ret >> 3); + *pValue = prop_ret; + return(XcmsSuccess); +} diff --git a/src/xcms/cmsTrig.c b/src/xcms/cmsTrig.c new file mode 100644 index 0000000..a1e9b50 --- /dev/null +++ b/src/xcms/cmsTrig.c @@ -0,0 +1,600 @@ +/* $Xorg: cmsTrig.c,v 1.3 2000/08/17 19:45:10 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * It should be pointed out that for simplicity's sake, the + * environment parameters are defined as floating point constants, + * rather than octal or hexadecimal initializations of allocated + * storage areas. This means that the range of allowed numbers + * may not exactly match the hardware's capabilities. For example, + * if the maximum positive double precision floating point number + * is EXACTLY 1.11...E100 and the constant "MAXDOUBLE is + * defined to be 1.11E100 then the numbers between 1.11E100 and + * 1.11...E100 are considered to be undefined. For most + * applications, this will cause no problems. + * + * An alternate method is to allocate a global static "double" variable, + * say "maxdouble", and use a union declaration and initialization + * to initialize it with the proper bits for the EXACT maximum value. + * This was not done because the only compilers available to the + * author did not fully support union initialization features. + * + */ + +/* + * EXTERNS + */ +extern double _XcmsSquareRoot(); + +/* + * FORWARD DECLARATIONS + */ +double _XcmsCosine(); +static double _XcmsModulo(); +static double _XcmsModuloF(); +static double _XcmsPolynomial(); +double _XcmsSine(); +double _XcmsArcTangent(); + +/* + * DEFINES + */ + +#ifdef __STDC__ +#define Const const +#else +#define Const /**/ +#endif +#define XCMS_MAXERROR 0.000001 +#define XCMS_MAXITER 10000 +#define XCMS_PI 3.14159265358979323846264338327950 +#define XCMS_TWOPI 6.28318530717958620 +#define XCMS_HALFPI 1.57079632679489660 +#define XCMS_FOURTHPI 0.785398163397448280 +#define XCMS_SIXTHPI 0.523598775598298820 +#define XCMS_RADIANS(d) ((d) * XCMS_PI / 180.0) +#define XCMS_DEGREES(r) ((r) * 180.0 / XCMS_PI) +#define XCMS_X6_UNDERFLOWS (4.209340e-52) /* X**6 almost underflows */ +#define XCMS_X16_UNDERFLOWS (5.421010e-20) /* X**16 almost underflows*/ +#define XCMS_CHAR_BIT 8 +#define XCMS_LONG_MAX 0x7FFFFFFF +#define XCMS_DEXPLEN 11 +#define XCMS_NBITS(type) (XCMS_CHAR_BIT * (int)sizeof(type)) +#define XCMS_FABS(x) ((x) < 0.0 ? -(x) : (x)) + +/* XCMS_DMAXPOWTWO - largest power of two exactly representable as a double */ +#ifdef _CRAY +#define XCMS_DMAXPOWTWO ((double)(1 < 47)) +#else +#define XCMS_DMAXPOWTWO ((double)(XCMS_LONG_MAX) * \ + (1L << (XCMS_NBITS(double)-XCMS_DEXPLEN) - XCMS_NBITS(long) + 1)) +#endif + +/* + * LOCAL VARIABLES + */ + +static double Const cos_pcoeffs[] = { + 0.12905394659037374438e7, + -0.37456703915723204710e6, + 0.13432300986539084285e5, + -0.11231450823340933092e3 +}; + +static double Const cos_qcoeffs[] = { + 0.12905394659037373590e7, + 0.23467773107245835052e5, + 0.20969518196726306286e3, + 1.0 +}; + +static double Const sin_pcoeffs[] = { + 0.20664343336995858240e7, + -0.18160398797407332550e6, + 0.35999306949636188317e4, + -0.20107483294588615719e2 +}; + +static double Const sin_qcoeffs[] = { + 0.26310659102647698963e7, + 0.39270242774649000308e5, + 0.27811919481083844087e3, + 1.0 +}; + +/* + * + * FUNCTION + * + * _XcmsCosine double precision cosine + * + * KEY WORDS + * + * cos + * machine independent routines + * trigonometric functions + * math libraries + * + * DESCRIPTION + * + * Returns double precision cosine of double precision + * floating point argument. + * + * USAGE + * + * double _XcmsCosine (x) + * double x; + * + * REFERENCES + * + * Computer Approximations, J.F. Hart et al, John Wiley & Sons, + * 1968, pp. 112-120. + * + * RESTRICTIONS + * + * The sin and cos routines are interactive in the sense that + * in the process of reducing the argument to the range -PI/4 + * to PI/4, each may call the other. Ultimately one or the + * other uses a polynomial approximation on the reduced + * argument. The sin approximation has a maximum relative error + * of 10**(-17.59) and the cos approximation has a maximum + * relative error of 10**(-16.18). + * + * These error bounds assume exact arithmetic + * in the polynomial evaluation. Additional rounding and + * truncation errors may occur as the argument is reduced + * to the range over which the polynomial approximation + * is valid, and as the polynomial is evaluated using + * finite-precision arithmetic. + * + * PROGRAMMER + * + * Fred Fish + * + * INTERNALS + * + * Computes cos(x) from: + * + * (1) Reduce argument x to range -PI to PI. + * + * (2) If x > PI/2 then call cos recursively + * using relation cos(x) = -cos(x - PI). + * + * (3) If x < -PI/2 then call cos recursively + * using relation cos(x) = -cos(x + PI). + * + * (4) If x > PI/4 then call sin using + * relation cos(x) = sin(PI/2 - x). + * + * (5) If x < -PI/4 then call cos using + * relation cos(x) = sin(PI/2 + x). + * + * (6) If x would cause underflow in approx + * evaluation arithmetic then return + * sqrt(1.0 - x**2). + * + * (7) By now x has been reduced to range + * -PI/4 to PI/4 and the approximation + * from HART pg. 119 can be used: + * + * cos(x) = ( p(y) / q(y) ) + * Where: + * + * y = x * (4/PI) + * + * p(y) = SUM [ Pj * (y**(2*j)) ] + * over j = {0,1,2,3} + * + * q(y) = SUM [ Qj * (y**(2*j)) ] + * over j = {0,1,2,3} + * + * P0 = 0.12905394659037374438571854e+7 + * P1 = -0.3745670391572320471032359e+6 + * P2 = 0.134323009865390842853673e+5 + * P3 = -0.112314508233409330923e+3 + * Q0 = 0.12905394659037373590295914e+7 + * Q1 = 0.234677731072458350524124e+5 + * Q2 = 0.2096951819672630628621e+3 + * Q3 = 1.0000... + * (coefficients from HART table #3843 pg 244) + * + * + * **** NOTE **** The range reduction relations used in + * this routine depend on the final approximation being valid + * over the negative argument range in addition to the positive + * argument range. The particular approximation chosen from + * HART satisfies this requirement, although not explicitly + * stated in the text. This may not be true of other + * approximations given in the reference. + * + */ + +double _XcmsCosine (x) +double x; +{ + auto double y; + auto double yt2; + double retval; + + if (x < -XCMS_PI || x > XCMS_PI) { + x = _XcmsModulo (x, XCMS_TWOPI); + if (x > XCMS_PI) { + x = x - XCMS_TWOPI; + } else if (x < -XCMS_PI) { + x = x + XCMS_TWOPI; + } + } + if (x > XCMS_HALFPI) { + retval = -(_XcmsCosine (x - XCMS_PI)); + } else if (x < -XCMS_HALFPI) { + retval = -(_XcmsCosine (x + XCMS_PI)); + } else if (x > XCMS_FOURTHPI) { + retval = _XcmsSine (XCMS_HALFPI - x); + } else if (x < -XCMS_FOURTHPI) { + retval = _XcmsSine (XCMS_HALFPI + x); + } else if (x < XCMS_X6_UNDERFLOWS && x > -XCMS_X6_UNDERFLOWS) { + retval = _XcmsSquareRoot (1.0 - (x * x)); + } else { + y = x / XCMS_FOURTHPI; + yt2 = y * y; + retval = _XcmsPolynomial (3, cos_pcoeffs, yt2) / _XcmsPolynomial (3, cos_qcoeffs, yt2); + } + return (retval); +} + + +/* + * FUNCTION + * + * _XcmsModulo double precision modulo + * + * KEY WORDS + * + * _XcmsModulo + * machine independent routines + * math libraries + * + * DESCRIPTION + * + * Returns double precision modulo of two double + * precision arguments. + * + * USAGE + * + * double _XcmsModulo (value, base) + * double value; + * double base; + * + * PROGRAMMER + * + * Fred Fish + * + */ +static double _XcmsModulo (value, base) +double value; +double base; +{ + auto double intpart; + + value /= base; + value = _XcmsModuloF (value, &intpart); + value *= base; + return(value); +} + + +/* + * frac = (double) _XcmsModuloF(double val, double *dp) + * return fractional part of 'val' + * set *dp to integer part of 'val' + * + * Note -> only compiled for the CA or KA. For the KB/MC, + * "math.c" instantiates a copy of the inline function + * defined in "math.h". + */ +static double +_XcmsModuloF(val, dp) +double val; +register double *dp; +{ + register double abs; + register double ip; + + /* should check for illegal values here - nan, inf, etc */ + abs = XCMS_FABS(val); + if (abs >= XCMS_DMAXPOWTWO) { + ip = val; + } else { + ip = abs + XCMS_DMAXPOWTWO; /* dump fraction */ + ip -= XCMS_DMAXPOWTWO; /* restore w/o frac */ + if (ip > abs) /* if it rounds up */ + ip -= 1.0; /* fix it */ + ip = XCMS_FABS(ip); + } + *dp = ip; + return (val - ip); /* signed fractional part */ +} + + +/* + * FUNCTION + * + * _XcmsPolynomial double precision polynomial evaluation + * + * KEY WORDS + * + * poly + * machine independent routines + * math libraries + * + * DESCRIPTION + * + * Evaluates a polynomial and returns double precision + * result. Is passed a the order of the polynomial, + * a pointer to an array of double precision polynomial + * coefficients (in ascending order), and the independent + * variable. + * + * USAGE + * + * double _XcmsPolynomial (order, coeffs, x) + * int order; + * double *coeffs; + * double x; + * + * PROGRAMMER + * + * Fred Fish + * + * INTERNALS + * + * Evalates the polynomial using recursion and the form: + * + * P(x) = P0 + x(P1 + x(P2 +...x(Pn))) + * + */ + +static double _XcmsPolynomial (order, coeffs, x) +register int order; +double Const *coeffs; +double x; +{ + auto double rtn_value; + +#if 0 + auto double curr_coeff; + if (order <= 0) { + rtn_value = *coeffs; + } else { + curr_coeff = *coeffs; /* Bug in Unisoft's compiler. Does not */ + coeffs++; /* generate good code for *coeffs++ */ + rtn_value = curr_coeff + x * _XcmsPolynomial (--order, coeffs, x); + } +#else /* ++jrb -- removed tail recursion */ + coeffs += order; + rtn_value = *coeffs--; + while(order-- > 0) + rtn_value = *coeffs-- + (x * rtn_value); +#endif + + return(rtn_value); +} + + +/* + * FUNCTION + * + * _XcmsSine double precision sine + * + * KEY WORDS + * + * sin + * machine independent routines + * trigonometric functions + * math libraries + * + * DESCRIPTION + * + * Returns double precision sine of double precision + * floating point argument. + * + * USAGE + * + * double _XcmsSine (x) + * double x; + * + * REFERENCES + * + * Computer Approximations, J.F. Hart et al, John Wiley & Sons, + * 1968, pp. 112-120. + * + * RESTRICTIONS + * + * The sin and cos routines are interactive in the sense that + * in the process of reducing the argument to the range -PI/4 + * to PI/4, each may call the other. Ultimately one or the + * other uses a polynomial approximation on the reduced + * argument. The sin approximation has a maximum relative error + * of 10**(-17.59) and the cos approximation has a maximum + * relative error of 10**(-16.18). + * + * These error bounds assume exact arithmetic + * in the polynomial evaluation. Additional rounding and + * truncation errors may occur as the argument is reduced + * to the range over which the polynomial approximation + * is valid, and as the polynomial is evaluated using + * finite-precision arithmetic. + * + * PROGRAMMER + * + * Fred Fish + * + * INTERNALS + * + * Computes sin(x) from: + * + * (1) Reduce argument x to range -PI to PI. + * + * (2) If x > PI/2 then call sin recursively + * using relation sin(x) = -sin(x - PI). + * + * (3) If x < -PI/2 then call sin recursively + * using relation sin(x) = -sin(x + PI). + * + * (4) If x > PI/4 then call cos using + * relation sin(x) = cos(PI/2 - x). + * + * (5) If x < -PI/4 then call cos using + * relation sin(x) = -cos(PI/2 + x). + * + * (6) If x is small enough that polynomial + * evaluation would cause underflow + * then return x, since sin(x) + * approaches x as x approaches zero. + * + * (7) By now x has been reduced to range + * -PI/4 to PI/4 and the approximation + * from HART pg. 118 can be used: + * + * sin(x) = y * ( p(y) / q(y) ) + * Where: + * + * y = x * (4/PI) + * + * p(y) = SUM [ Pj * (y**(2*j)) ] + * over j = {0,1,2,3} + * + * q(y) = SUM [ Qj * (y**(2*j)) ] + * over j = {0,1,2,3} + * + * P0 = 0.206643433369958582409167054e+7 + * P1 = -0.18160398797407332550219213e+6 + * P2 = 0.359993069496361883172836e+4 + * P3 = -0.2010748329458861571949e+2 + * Q0 = 0.263106591026476989637710307e+7 + * Q1 = 0.3927024277464900030883986e+5 + * Q2 = 0.27811919481083844087953e+3 + * Q3 = 1.0000... + * (coefficients from HART table #3063 pg 234) + * + * + * **** NOTE **** The range reduction relations used in + * this routine depend on the final approximation being valid + * over the negative argument range in addition to the positive + * argument range. The particular approximation chosen from + * HART satisfies this requirement, although not explicitly + * stated in the text. This may not be true of other + * approximations given in the reference. + * + */ + +double +_XcmsSine (x) +double x; +{ + double y; + double yt2; + double retval; + + if (x < -XCMS_PI || x > XCMS_PI) { + x = _XcmsModulo (x, XCMS_TWOPI); + if (x > XCMS_PI) { + x = x - XCMS_TWOPI; + } else if (x < -XCMS_PI) { + x = x + XCMS_TWOPI; + } + } + if (x > XCMS_HALFPI) { + retval = -(_XcmsSine (x - XCMS_PI)); + } else if (x < -XCMS_HALFPI) { + retval = -(_XcmsSine (x + XCMS_PI)); + } else if (x > XCMS_FOURTHPI) { + retval = _XcmsCosine (XCMS_HALFPI - x); + } else if (x < -XCMS_FOURTHPI) { + retval = -(_XcmsCosine (XCMS_HALFPI + x)); + } else if (x < XCMS_X6_UNDERFLOWS && x > -XCMS_X6_UNDERFLOWS) { + retval = x; + } else { + y = x / XCMS_FOURTHPI; + yt2 = y * y; + retval = y * (_XcmsPolynomial (3, sin_pcoeffs, yt2) / _XcmsPolynomial(3, sin_qcoeffs, yt2)); + } + return(retval); +} + + +/* + * NAME + * _XcmsArcTangent + * + * SYNOPSIS + */ +double +_XcmsArcTangent(x) + double x; +/* + * DESCRIPTION + * Computes the arctangent. + * This is an implementation of the Gauss algorithm as + * described in: + * Forman S. Acton, Numerical Methods That Work, + * New York, NY, Harper & Row, 1970. + * + * RETURNS + * Returns the arctangent + */ +{ + double ai, a1, bi, b1, l, d; + double maxerror; + int i; + + if (x == 0.0) { + return (0.0); + } + if (x < 1.0) { + maxerror = x * XCMS_MAXERROR; + } else { + maxerror = XCMS_MAXERROR; + } + ai = _XcmsSquareRoot( 1.0 / (1.0 + (x * x)) ); + bi = 1.0; + for (i = 0; i < XCMS_MAXITER; i++) { + a1 = (ai + bi) / 2.0; + b1 = _XcmsSquareRoot((a1 * bi)); + if (a1 == b1) + break; + d = XCMS_FABS(a1 - b1); + if (d < maxerror) + break; + ai = a1; + bi = b1; + } + + l = ((a1 > b1) ? b1 : a1); + + a1 = _XcmsSquareRoot(1 + (x * x)); + return (x / (a1 * l)); +} diff --git a/src/xcms/uvY.c b/src/xcms/uvY.c new file mode 100644 index 0000000..3438d88 --- /dev/null +++ b/src/xcms/uvY.c @@ -0,0 +1,409 @@ +/* $Xorg: uvY.c,v 1.3 2000/08/17 19:45:23 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of XCMS based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * + * NAME + * CIEuvy.c + * + * DESCRIPTION + * This file contains routines that support the CIE u'v'Y + * color space to include conversions to and from the CIE + * XYZ space. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + */ + +#include <X11/Xos.h> +#include "Xlibint.h" +#include "Xcmsint.h" + + +/* + * EXTERNS + */ +extern char _XcmsCIEuvY_prefix[]; + + +/* + * FORWARD DECLARATIONS + */ + +static int CIEuvY_ParseString(); +Status _XcmsCIEuvY_ValidSpec(); +/* + * DEFINES + * Internal definitions that need NOT be exported to any package + * or program using this package. + */ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif + + +/* + * LOCAL VARIABLES + */ + + /* + * NULL terminated list of functions applied to get from CIEuvY to CIEXYZ + */ +static XcmsConversionProc Fl_CIEuvY_to_CIEXYZ[] = { + XcmsCIEuvYToCIEXYZ, + NULL +}; + + /* + * NULL terminated list of functions applied to get from CIEXYZ to CIEuvY + */ +static XcmsConversionProc Fl_CIEXYZ_to_CIEuvY[] = { + XcmsCIEXYZToCIEuvY, + NULL +}; + + +/* + * GLOBALS + */ + + /* + * CIE uvY Color Space + */ +XcmsColorSpace XcmsCIEuvYColorSpace = + { + _XcmsCIEuvY_prefix, /* prefix */ + XcmsCIEuvYFormat, /* id */ + CIEuvY_ParseString, /* parseString */ + Fl_CIEuvY_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_CIEuvY, /* from_CIEXYZ */ + 1 + }; + + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIEuvY_ParseString + * + * SYNOPSIS + */ +static int +CIEuvY_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsCIEuvYFormat. + * The assumed CIEuvY string syntax is: + * CIEuvY:<u>/<v>/<Y> + * Where u, v, and Y are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsCIEuvY_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.CIEuvY.u_prime, + &pColor->spec.CIEuvY.v_prime, + &pColor->spec.CIEuvY.Y) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsCIEuvYFormat; + pColor->pixel = 0; + return(_XcmsCIEuvY_ValidSpec(pColor)); +} + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * XcmsCIEuvY_ValidSpec + * + * SYNOPSIS + */ +Status +_XcmsCIEuvY_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks if color specification valid for CIE u'v'Y. + * + * RETURNS + * XcmsFailure if invalid, + * XcmsSuccess if valid. + * + */ +{ + if (pColor->format != XcmsCIEuvYFormat + || + (pColor->spec.CIEuvY.Y < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIEuvY.Y > 1.0 + XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEuvYToCIEXYZ - convert CIEuvY to CIEXYZ + * + * SYNOPSIS + */ +Status +XcmsCIEuvYToCIEXYZ(ccc, puvY_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *puvY_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIEuvY format to CIEXYZ format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsCIEXYZ XYZ_return; + XcmsColor whitePt; + int i; + XcmsColor *pColor = pColors_in_out; + XcmsFloat div, x, y, z, Y; + + /* + * Check arguments + * Postpone checking puvY_WhitePt until it is actually needed + * otherwise converting between XYZ and uvY will fail. + */ + if (pColors_in_out == NULL) { + return(XcmsFailure); + } + + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is CIEuvY */ + if (!_XcmsCIEuvY_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* + * Convert to CIEXYZ + */ + + Y = pColor->spec.CIEuvY.Y; + + /* Convert color u'v' to xyz space */ + div = (6.0 * pColor->spec.CIEuvY.u_prime) - (16.0 * pColor->spec.CIEuvY.v_prime) + 12.0; + if (div == 0.0) { + /* use white point since div == 0 */ + if (puvY_WhitePt == NULL ) { + return(XcmsFailure); + } + /* + * Make sure white point is in CIEuvY form + */ + if (puvY_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)puvY_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, 1, + XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + puvY_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (puvY_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + div = (6.0 * puvY_WhitePt->spec.CIEuvY.u_prime) - + (16.0 * puvY_WhitePt->spec.CIEuvY.v_prime) + 12.0; + if (div == 0) { + /* internal error */ + return(XcmsFailure); + } + x = 9.0 * puvY_WhitePt->spec.CIEuvY.u_prime / div; + y = 4.0 * puvY_WhitePt->spec.CIEuvY.v_prime / div; + } else { + x = 9.0 * pColor->spec.CIEuvY.u_prime / div; + y = 4.0 * pColor->spec.CIEuvY.v_prime / div; + } + z = 1.0 - x - y; + + /* Convert from xyz to XYZ */ + /* Conversion uses color normalized lightness based on Y */ + if (y != 0.0) { + XYZ_return.X = x * Y / y; + } else { + XYZ_return.X = x; + } + XYZ_return.Y = Y; + if (y != 0.0) { + XYZ_return.Z = z * Y / y; + } else { + XYZ_return.Z = z; + } + + memcpy((char *)&pColor->spec.CIEXYZ, (char *)&XYZ_return, sizeof(XcmsCIEXYZ)); + /* Identify that format is now CIEXYZ */ + pColor->format = XcmsCIEXYZFormat; + } + + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEXYZToCIEuvY - convert CIEXYZ to CIEuvY + * + * SYNOPSIS + */ +Status +XcmsCIEXYZToCIEuvY(ccc, puvY_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *puvY_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIEXYZ format to CIEuvY format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsCIEuvY uvY_return; + XcmsColor whitePt; + int i; + XcmsColor *pColor = pColors_in_out; + XcmsFloat div; + + /* + * Check arguments + * Postpone checking puvY_WhitePt until it is actually needed + * otherwise converting between XYZ and uvY will fail. + */ + if (pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEuvY form + */ + for (i = 0; i < nColors; i++, pColor++) { + + /* Make sure original format is CIEXYZ */ + if (!_XcmsCIEXYZ_ValidSpec(pColor)) { + return(XcmsFailure); + } + + /* Convert to CIEuvY */ + div = pColor->spec.CIEXYZ.X + (15.0 * pColor->spec.CIEXYZ.Y) + + (3.0 * pColor->spec.CIEXYZ.Z); + if (div == 0.0) { + /* Use white point since div == 0.0 */ + if (puvY_WhitePt == NULL ) { + return(XcmsFailure); + } + /* + * Make sure white point is in CIEuvY form + */ + if (puvY_WhitePt->format != XcmsCIEuvYFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)puvY_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, 1, + XcmsCIEuvYFormat)) { + return(XcmsFailure); + } + puvY_WhitePt = &whitePt; + } + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (puvY_WhitePt->spec.CIEuvY.Y != 1.0) { + return(XcmsFailure); + } + uvY_return.Y = pColor->spec.CIEXYZ.Y; + uvY_return.u_prime = puvY_WhitePt->spec.CIEuvY.u_prime; + uvY_return.v_prime = puvY_WhitePt->spec.CIEuvY.v_prime; + } else { + uvY_return.u_prime = 4.0 * pColor->spec.CIEXYZ.X / div; + uvY_return.v_prime = 9.0 * pColor->spec.CIEXYZ.Y / div; + uvY_return.Y = pColor->spec.CIEXYZ.Y; + } + + memcpy((char *)&pColor->spec.CIEuvY, (char *)&uvY_return, sizeof(XcmsCIEuvY)); + /* Identify that format is now CIEuvY */ + pColor->format = XcmsCIEuvYFormat; + } + + return(XcmsSuccess); +} diff --git a/src/xcms/xyY.c b/src/xcms/xyY.c new file mode 100644 index 0000000..00bd841 --- /dev/null +++ b/src/xcms/xyY.c @@ -0,0 +1,381 @@ +/* $Xorg: xyY.c,v 1.3 2000/08/17 19:45:23 cpqbld Exp $ */ + +/* + * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. + * All Rights Reserved + * + * This file is a component of an X Window System-specific implementation + * of Xcms based on the TekColor Color Management System. Permission is + * hereby granted to use, copy, modify, sell, and otherwise distribute this + * software and its documentation for any purpose and without fee, provided + * that this copyright, permission, and disclaimer notice is reproduced in + * all copies of this software and in supporting documentation. TekColor + * is a trademark of Tektronix, Inc. + * + * Tektronix makes no representation about the suitability of this software + * for any purpose. It is provided "as is" and with all faults. + * + * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, + * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. + * + * NAME + * CIExyY.c + * + * DESCRIPTION + * This file contains routines that support the CIE xyY + * color space to include conversions to and from the CIE + * XYZ space. + * + * DOCUMENTATION + * "TekColor Color Management System, System Implementor's Manual" + */ + +#include <stdio.h> +#include <X11/Xos.h> +#include "Xlibint.h" +#include "Xcmsint.h" + +/* + * DEFINES + */ +#define EPS 0.00001 /* some extremely small number */ +#ifdef DBL_EPSILON +# define XMY_DBL_EPSILON DBL_EPSILON +#else +# define XMY_DBL_EPSILON 0.00001 +#endif + +/* + * EXTERNS + */ + +extern char _XcmsCIExyY_prefix[]; + +/* + * FORWARD DECLARATIONS + */ + +static int CIExyY_ParseString(); +static Status XcmsCIExyY_ValidSpec(); + + +/* + * LOCAL VARIABLES + */ + + /* + * NULL terminated list of functions applied to get from CIExyY to CIEXYZ + */ +static XcmsConversionProc Fl_CIExyY_to_CIEXYZ[] = { + XcmsCIExyYToCIEXYZ, + NULL +}; + + /* + * NULL terminated list of functions applied to get from CIEXYZ to CIExyY + */ +static XcmsConversionProc Fl_CIEXYZ_to_CIExyY[] = { + XcmsCIEXYZToCIExyY, + NULL +}; + + +/* + * GLOBALS + */ + + /* + * CIE xyY Color Space + */ +XcmsColorSpace XcmsCIExyYColorSpace = + { + _XcmsCIExyY_prefix, /* prefix */ + XcmsCIExyYFormat, /* id */ + CIExyY_ParseString, /* parseString */ + Fl_CIExyY_to_CIEXYZ, /* to_CIEXYZ */ + Fl_CIEXYZ_to_CIExyY, /* from_CIEXYZ */ + 1 + }; + + + +/************************************************************************ + * * + * PRIVATE ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIExyY_ParseString + * + * SYNOPSIS + */ +static int +CIExyY_ParseString(spec, pColor) + register char *spec; + XcmsColor *pColor; +/* + * DESCRIPTION + * This routines takes a string and attempts to convert + * it into a XcmsColor structure with XcmsCIExyYFormat. + * The assumed CIExyY string syntax is: + * CIExyY:<x>/<y>/<Y> + * Where x, y, and Y are in string input format for floats + * consisting of: + * a. an optional sign + * b. a string of numbers possibly containing a decimal point, + * c. an optional exponent field containing an 'E' or 'e' + * followed by a possibly signed integer string. + * + * RETURNS + * 0 if failed, non-zero otherwise. + */ +{ + int n; + char *pchar; + + if ((pchar = strchr(spec, ':')) == NULL) { + return(XcmsFailure); + } + n = (int)(pchar - spec); + + /* + * Check for proper prefix. + */ + if (strncmp(spec, _XcmsCIExyY_prefix, n) != 0) { + return(XcmsFailure); + } + + /* + * Attempt to parse the value portion. + */ + if (sscanf(spec + n + 1, "%lf/%lf/%lf", + &pColor->spec.CIExyY.x, + &pColor->spec.CIExyY.y, + &pColor->spec.CIExyY.Y) != 3) { + return(XcmsFailure); + } + pColor->format = XcmsCIExyYFormat; + pColor->pixel = 0; + return(XcmsCIExyY_ValidSpec(pColor)); +} + + + +/************************************************************************ + * * + * PUBLIC ROUTINES * + * * + ************************************************************************/ + +/* + * NAME + * CIExyY_ValidSpec() + * + * SYNOPSIS + */ +static Status +XcmsCIExyY_ValidSpec(pColor) + XcmsColor *pColor; +/* + * DESCRIPTION + * Checks a valid CIExyY color specification. + * + * RETURNS + * XcmsFailure if invalid. + * XcmsSuccess if valid. + * + */ +{ + if (pColor->format != XcmsCIExyYFormat + || + (pColor->spec.CIExyY.x < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIExyY.x > 1.0 + XMY_DBL_EPSILON) + || + (pColor->spec.CIExyY.y < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIExyY.y > 1.0 + XMY_DBL_EPSILON) + || + (pColor->spec.CIExyY.Y < 0.0 - XMY_DBL_EPSILON) + || + (pColor->spec.CIExyY.Y > 1.0 + XMY_DBL_EPSILON)) { + return(XcmsFailure); + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIExyYToCIEXYZ - convert CIExyY to CIEXYZ + * + * SYNOPSIS + */ +Status +XcmsCIExyYToCIEXYZ(ccc, pxyY_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pxyY_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIExyY format to CIEXYZ format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + */ +{ + XcmsColor *pColor = pColors_in_out; + XcmsColor whitePt; + XcmsCIEXYZ XYZ_return; + XcmsFloat div; /* temporary storage in case divisor is zero */ + XcmsFloat u, v, x, y, z; /* temporary storage */ + register int i; + + /* + * Check arguments + */ + if (pxyY_WhitePt == NULL || pColors_in_out == NULL) { + return(XcmsFailure); + } + + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + /* Make sure original format is CIExyY and valid */ + if (!XcmsCIExyY_ValidSpec(pColor)) { + return(XcmsFailure); + } + + if ((div = (-2 * pColor->spec.CIExyY.x) + (12 * pColor->spec.CIExyY.y) + 3) == 0.0) { + /* Note that the divisor is zero */ + /* This return is abitrary. */ + XYZ_return.X = 0; + XYZ_return.Y = 0; + XYZ_return.Z = 0; + } else { + /* + * Make sure white point is in CIEXYZ form + */ + if (pxyY_WhitePt->format != XcmsCIEXYZFormat) { + /* Make copy of the white point because we're going to modify it */ + memcpy((char *)&whitePt, (char *)pxyY_WhitePt, sizeof(XcmsColor)); + if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL, 1, + XcmsCIEXYZFormat)) { + return(XcmsFailure); + } + pxyY_WhitePt = &whitePt; + } + + /* Make sure it is a white point, i.e., Y == 1.0 */ + if (pxyY_WhitePt->spec.CIEXYZ.Y != 1.0) { + return(XcmsFailure); + } + + /* Convert from xyY to uvY to XYZ */ + u = (4 * pColor->spec.CIExyY.x) / div; + v = (9 * pColor->spec.CIExyY.y) / div; + div = (6.0 * u) - (16.0 * v) + 12.0; + if (div == 0.0) { + /* Note that the divisor is zero */ + /* This return is abitrary. */ + if ((div = (6.0 * whitePt.spec.CIEuvY.u_prime) - + (16.0 * whitePt.spec.CIEuvY.v_prime) + 12.0) == 0.0) { + div = EPS; + } + x = 9.0 * whitePt.spec.CIEuvY.u_prime / div; + y = 4.0 * whitePt.spec.CIEuvY.u_prime / div; + } else { + /* convert u, v to small xyz */ + x = 9.0 * u / div; + y = 4.0 * v / div; + } + z = 1.0 - x - y; + if (y == 0.0) y = EPS; /* Have to worry about divide by 0 */ + XYZ_return.Y = pColor->spec.CIExyY.Y; + XYZ_return.X = x * XYZ_return.Y / y; + XYZ_return.Z = z * XYZ_return.Y / y; + } + + /* Copy result to pColor */ + memcpy ((char *)&pColor->spec, (char *)&XYZ_return, sizeof(XcmsCIEXYZ)); + + /* Identify that the format is now CIEXYZ */ + pColor->format = XcmsCIEXYZFormat; + } + return(XcmsSuccess); +} + + +/* + * NAME + * XcmsCIEXYZToCIExyY - convert CIEXYZ to CIExyY + * + * SYNOPSIS + */ +/* ARGSUSED */ +Status +XcmsCIEXYZToCIExyY(ccc, pxyY_WhitePt, pColors_in_out, nColors) + XcmsCCC ccc; + XcmsColor *pxyY_WhitePt; + XcmsColor *pColors_in_out; + unsigned int nColors; +/* + * DESCRIPTION + * Converts color specifications in an array of XcmsColor + * structures from CIEXYZ format to CIExyY format. + * + * RETURNS + * XcmsFailure if failed, + * XcmsSuccess if succeeded. + * + */ +{ + XcmsColor *pColor = pColors_in_out; + XcmsCIExyY xyY_return; + XcmsFloat div; /* temporary storage in case divisor is zero */ + register int i; + + /* + * Check arguments + * pxyY_WhitePt ignored + */ + if (pColors_in_out == NULL) { + return(XcmsFailure); + } + + /* + * Now convert each XcmsColor structure to CIEXYZ form + */ + for (i = 0; i < nColors; i++, pColor++) { + + if (!_XcmsCIEXYZ_ValidSpec(pColor)) { + return(XcmsFailure); + } + /* Now convert for XYZ to xyY */ + if ((div = pColor->spec.CIEXYZ.X + pColor->spec.CIEXYZ.Y + pColor->spec.CIEXYZ.Z) == 0.0) { + div = EPS; + } + xyY_return.x = pColor->spec.CIEXYZ.X / div; + xyY_return.y = pColor->spec.CIEXYZ.Y / div; + xyY_return.Y = pColor->spec.CIEXYZ.Y; + + /* Copy result to pColor */ + memcpy ((char *)&pColor->spec, (char *)&xyY_return, sizeof(XcmsCIExyY)); + + /* Identify that the format is now CIEXYZ */ + pColor->format = XcmsCIExyYFormat; + } + return(XcmsSuccess); +} |