home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / X / TekHVCGcVC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  8.8 KB  |  264 lines

  1. /* $XConsortium: TekHVCGcVC.c,v 1.9 91/09/05 15:58:10 dave Exp $" */
  2.  
  3. /*
  4.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  5.  *     All Rights Reserved
  6.  * 
  7.  * This file is a component of an X Window System-specific implementation
  8.  * of Xcms based on the TekColor Color Management System.  TekColor is a
  9.  * trademark of Tektronix, Inc.  The term "TekHVC" designates a particular
  10.  * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent
  11.  * foreign patents pending).  Permission is hereby granted to use, copy,
  12.  * modify, sell, and otherwise distribute this software and its
  13.  * documentation for any purpose and without fee, provided that:
  14.  * 
  15.  * 1. This copyright, permission, and disclaimer notice is reproduced in
  16.  *    all copies of this software and any modification thereof and in
  17.  *    supporting documentation; 
  18.  * 2. Any color-handling application which displays TekHVC color
  19.  *    cooordinates identifies these as TekHVC color coordinates in any
  20.  *    interface that displays these coordinates and in any associated
  21.  *    documentation;
  22.  * 3. The term "TekHVC" is always used, and is only used, in association
  23.  *    with the mathematical derivations of the TekHVC Color Space,
  24.  *    including those provided in this file and any equivalent pathways and
  25.  *    mathematical derivations, regardless of digital (e.g., floating point
  26.  *    or integer) representation.
  27.  * 
  28.  * Tektronix makes no representation about the suitability of this software
  29.  * for any purpose.  It is provided "as is" and with all faults.
  30.  * 
  31.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  32.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  33.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  34.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  35.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  36.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  37.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  38.  *
  39.  *    NAME
  40.  *        TekHVCGcVC.c
  41.  *
  42.  *    DESCRIPTION
  43.  *        Source for XcmsTekHVCClipVC() gamut
  44.  *        compression function.
  45.  */
  46.  
  47. #include "Xlibint.h"
  48. #include "Xcmsint.h"
  49. #include <math.h>
  50.  
  51. /*
  52.  *    INTERNALS
  53.  *        Internal defines that need NOT be exported to any package or
  54.  *        program using this package.
  55.  */
  56. #define MAXBISECTCOUNT    100
  57.  
  58. /*
  59.  *    EXTERNS
  60.  */
  61. extern int _XcmsTekHVC_CheckModify();
  62. extern Status _XcmsTekHVCQueryMaxVCRGB();
  63. extern XcmsColorSpace XcmsTekHVCColorSpace;
  64. extern XcmsFunctionSet    XcmsLinearRGBFunctionSet;
  65.  
  66.  
  67. /************************************************************************
  68.  *                                    *
  69.  *             PUBLIC ROUTINES                *
  70.  *                                    *
  71.  ************************************************************************/
  72.  
  73. /*
  74.  *    NAME
  75.  *        XcmsTekHVCClipVC - Return the closest value and chroma
  76.  *
  77.  *    SYNOPSIS
  78.  */
  79. /* ARGSUSED */
  80. Status
  81. XcmsTekHVCClipVC (ccc, pColors_in_out, nColors, i, pCompressed)
  82.     XcmsCCC ccc;
  83.     XcmsColor *pColors_in_out;
  84.     unsigned int nColors;
  85.     unsigned int i;
  86.     Bool *pCompressed;
  87. /*
  88.  *    DESCRIPTION
  89.  *        This routine will find the closest value and chroma 
  90.  *        for a specific hue.  The color input is converted to
  91.  *        HVC format and returned as CIE XYZ format.
  92.  *
  93.  *        Since this routine works with the value within
  94.  *        pColor_in_out intermediate results may be returned
  95.  *        even though it may be invalid.
  96.  *
  97.  *    RETURNS
  98.  *        XcmsFailure - Failure
  99.  *              XcmsSuccess - Succeeded
  100.  *
  101.  */
  102. {
  103.     Status retval;
  104.     XcmsCCCRec    myCCC;
  105.     XcmsColor  *pColor;
  106.     XcmsColor  hvc_max;
  107.     XcmsRGBi   rgb_max;
  108.     int          nCount, nMaxCount, nI, nILast;
  109.     XcmsFloat  Chroma, Value, bestChroma, bestValue, nT, saveDist, tmpDist;
  110.  
  111.     /*
  112.      * Insure TekHVC installed
  113.      */
  114.     if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) {
  115.     return(XcmsFailure);
  116.     }
  117.  
  118.     /* Use my own CCC */
  119.     bcopy ((char *)ccc, (char *)&myCCC, sizeof(XcmsCCCRec));
  120.     myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* inherit screen white pt */
  121.     myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression func */
  122.  
  123.     /*
  124.      * Color specification passed as input can be assumed to:
  125.      *    1. Be in XcmsCIEXYZFormat
  126.      *    2. Already be white point adjusted for the Screen White Point.
  127.      *        This means that the white point now associated with this
  128.      *        color spec is the Screen White Point (even if the
  129.      *        ccc->clientWhitePt differs).
  130.      */
  131.  
  132.     pColor = pColors_in_out + i;
  133.  
  134.     if (ccc->visual->class < StaticColor &&
  135.         FunctionSetOfCCC(ccc) != (XPointer) &XcmsLinearRGBFunctionSet) {
  136.     /*
  137.      * GRAY !
  138.      */
  139.     _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt,
  140.         1, XcmsTekHVCFormat);
  141.     pColor->spec.TekHVC.H = pColor->spec.TekHVC.C = 0.0;
  142.     _XcmsDIConvertColors(ccc, pColor, &ccc->pPerScrnInfo->screenWhitePt,
  143.         1, XcmsCIEXYZFormat);
  144.     if (pCompressed) {
  145.         *(pCompressed + i) = True;
  146.     }
  147.     return(XcmsSuccess);
  148.     } else {
  149.     /* Convert from CIEXYZ to TekHVC format */
  150.     if (_XcmsDIConvertColors(&myCCC, pColor,
  151.         &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat)
  152.         == XcmsFailure) {
  153.         return(XcmsFailure);
  154.     }
  155.  
  156.     if (!_XcmsTekHVC_CheckModify(pColor)) {
  157.         return (XcmsFailure);
  158.     }
  159.  
  160.     /* Step 1: compute the maximum value and chroma for this hue. */
  161.     /*         This copy may be overkill but it preserves the pixel etc. */
  162.     bcopy((char *)pColor, (char *)&hvc_max, sizeof(XcmsColor));
  163.     if (_XcmsTekHVCQueryMaxVCRGB (&myCCC, hvc_max.spec.TekHVC.H, &hvc_max,
  164.         &rgb_max) == XcmsFailure) {
  165.         return (XcmsFailure);
  166.     }
  167.  
  168.     /* Now check and return the appropriate value */
  169.     if (pColor->spec.TekHVC.V == hvc_max.spec.TekHVC.V) {
  170.         /* When the value input is equal to the maximum value */
  171.         /* merely return the chroma for that value. */
  172.         pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C;
  173.         retval = _XcmsDIConvertColors(&myCCC, pColor,
  174.             &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat);
  175.     }
  176.  
  177.     if (pColor->spec.TekHVC.V < hvc_max.spec.TekHVC.V) {
  178.         /* return the intersection of the perpindicular line through     */
  179.         /* the value and chroma given and the line from 0,0 and hvc_max. */
  180.         Chroma = pColor->spec.TekHVC.C;
  181.         Value = pColor->spec.TekHVC.V;
  182.         pColor->spec.TekHVC.C = 
  183.            (Value + (hvc_max.spec.TekHVC.C / hvc_max.spec.TekHVC.V * Chroma)) /
  184.            ((hvc_max.spec.TekHVC.V / hvc_max.spec.TekHVC.C) +
  185.         (hvc_max.spec.TekHVC.C / hvc_max.spec.TekHVC.V));
  186.         if (pColor->spec.TekHVC.C >= hvc_max.spec.TekHVC.C) {
  187.         pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C;
  188.         pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V;
  189.         } else {
  190.         pColor->spec.TekHVC.V = pColor->spec.TekHVC.C *
  191.                     hvc_max.spec.TekHVC.V / hvc_max.spec.TekHVC.C;
  192.         }
  193.         retval = _XcmsDIConvertColors(&myCCC, pColor,
  194.             &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat);
  195.         return (retval);
  196.     }
  197.  
  198.     /* return the closest point on the upper part of the hue leaf. */
  199.     /* must do a bisection here to compute the delta e. */
  200.     nMaxCount = MAXBISECTCOUNT;
  201.     nI =     nMaxCount / 2;
  202.     bestValue = Value =  pColor->spec.TekHVC.V;
  203.     bestChroma = Chroma = pColor->spec.TekHVC.C;
  204.     saveDist = (XcmsFloat) XCMS_SQRT ((double) (((Chroma - hvc_max.spec.TekHVC.C) *
  205.                            (Chroma - hvc_max.spec.TekHVC.C)) +
  206.                           ((Value - hvc_max.spec.TekHVC.V) *
  207.                            (Value - hvc_max.spec.TekHVC.V))));
  208.     for (nCount = 0; nCount < nMaxCount; nCount++) {
  209.         nT = (XcmsFloat) nI / (XcmsFloat) nMaxCount;
  210.         pColor->spec.RGBi.red   = rgb_max.red * (1.0 - nT) + nT;
  211.         pColor->spec.RGBi.green = rgb_max.green * (1.0 - nT) + nT;
  212.         pColor->spec.RGBi.blue  = rgb_max.blue * (1.0 - nT) + nT;
  213.         pColor->format = XcmsRGBiFormat;
  214.  
  215.         /* Convert from RGBi to HVC */
  216.         if (_XcmsConvertColorsWithWhitePt(&myCCC, pColor,
  217.             &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat,
  218.             (Bool *) NULL)
  219.             == XcmsFailure) {
  220.         return (XcmsFailure);
  221.         }
  222.         if (!_XcmsTekHVC_CheckModify(pColor)) {
  223.         return (XcmsFailure);
  224.         }
  225.         tmpDist = (XcmsFloat) XCMS_SQRT ((double) 
  226.             (((Chroma - pColor->spec.TekHVC.C) *
  227.               (Chroma - pColor->spec.TekHVC.C)) +
  228.              ((Value - pColor->spec.TekHVC.V) *
  229.               (Value - pColor->spec.TekHVC.V))));
  230.         nILast = nI;
  231.         if (tmpDist > saveDist) {
  232.         nI /= 2;
  233.         } else {
  234.         nI = (nMaxCount + nI) / 2;
  235.         saveDist = tmpDist;
  236.         bestValue = pColor->spec.TekHVC.V;
  237.         bestChroma = pColor->spec.TekHVC.C;        
  238.         }
  239.         if (nI == nILast || nI == 0) {
  240.         break;
  241.         }
  242.  
  243.     }
  244.  
  245.     if (bestChroma >= hvc_max.spec.TekHVC.C) {
  246.         pColor->spec.TekHVC.C = hvc_max.spec.TekHVC.C;
  247.         pColor->spec.TekHVC.V = hvc_max.spec.TekHVC.V;
  248.     } else {
  249.         pColor->spec.TekHVC.C = bestChroma;
  250.         pColor->spec.TekHVC.V = bestValue;
  251.     }
  252.     if (!_XcmsTekHVC_CheckModify(pColor)) {
  253.         return (XcmsFailure);
  254.     }
  255.     retval = _XcmsDIConvertColors(&myCCC, pColor,
  256.         &myCCC.pPerScrnInfo->screenWhitePt, 1, XcmsCIEXYZFormat);
  257.  
  258.     if (retval != XcmsFailure && pCompressed != NULL) {
  259.         *(pCompressed + i) = True;
  260.     }
  261.     return(retval);
  262.     }
  263. }
  264.