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

  1. /* $XConsortium: CIELabMxC.c,v 1.2 91/07/25 01:07:18 rws Exp $ */
  2.  
  3. /*
  4.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  5.  *     All Rights Reserved
  6.  * 
  7.  * This file is a component of an X Window System-specific implementation
  8.  * of XCMS based on the TekColor Color Management System.  Permission is
  9.  * hereby granted to use, copy, modify, sell, and otherwise distribute this
  10.  * software and its documentation for any purpose and without fee, provided
  11.  * that this copyright, permission, and disclaimer notice is reproduced in
  12.  * all copies of this software and in supporting documentation.  TekColor
  13.  * is a trademark of Tektronix, Inc.
  14.  * 
  15.  * Tektronix makes no representation about the suitability of this software
  16.  * for any purpose.  It is provided "as is" and with all faults.
  17.  * 
  18.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  19.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  20.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  21.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  22.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  23.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  24.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  *
  27.  *
  28.  *    NAME
  29.  *        CIELabMxC.c
  30.  *
  31.  *    DESCRIPTION
  32.  *        Source for the XcmsCIELabQueryMaxC() gamut boundary
  33.  *        querying routine.
  34.  *
  35.  */
  36.  
  37. #include "Xlibint.h"
  38. #include "Xcmsint.h"
  39. #include <math.h>
  40.  
  41. /*
  42.  *    DEFINES
  43.  */
  44. #define MAXBISECTCOUNT    100
  45. #define EPS            (XcmsFloat)0.001
  46. #define START_CHROMA    (XcmsFloat)3.6
  47. #define TOPL        (XcmsFloat)100.0
  48.  
  49. /*
  50.  *    EXTERNS
  51.  */
  52. extern Status _XcmsCIELabQueryMaxLCRGB();
  53.  
  54.  
  55. /************************************************************************
  56.  *                                    *
  57.  *             PUBLIC ROUTINES                *
  58.  *                                    *
  59.  ************************************************************************/
  60.  
  61. /*
  62.  *    NAME
  63.  *        XcmsCIELabQueryMaxC - max chroma for a hue_angle and L_star
  64.  *
  65.  *    SYNOPSIS
  66.  */
  67. Status
  68. XcmsCIELabQueryMaxC(ccc, hue_angle, L_star, pColor_return)
  69.     XcmsCCC ccc;
  70.     XcmsFloat hue_angle;        /* hue angle in degrees */
  71.     XcmsFloat L_star;
  72.     XcmsColor *pColor_return;
  73. /*
  74.  *    DESCRIPTION
  75.  *        Return the maximum chroma for a specific hue_angle and L_star.
  76.  *        The returned format is in XcmsCIELabFormat.
  77.  *
  78.  *
  79.  *    ASSUMPTIONS
  80.  *        This routine assumes that the white point associated with
  81.  *        the color specification is the Screen White Point.  The
  82.  *        Screen White Point will also be associated with the
  83.  *        returned color specification.
  84.  *
  85.  *    RETURNS
  86.  *        XcmsFailure - Failure
  87.  *              XcmsSuccess - Succeeded
  88.  *
  89.  */
  90. {
  91.     XcmsCCCRec    myCCC;
  92.     XcmsColor  tmp;
  93.     XcmsColor  max_lc;
  94.     XcmsFloat n_L_star, last_L_star, prev_L_star;
  95.     XcmsFloat hue, lastaStar, lastbStar, /*lastChroma,*/ maxDist, nT, rFactor;
  96.     XcmsRGBi   rgb_saved;
  97.     int nCount, nMaxCount;
  98.  
  99.     /*
  100.      * Check Arguments
  101.      */
  102.     if (ccc == NULL || pColor_return == NULL) {
  103.     return(XcmsFailure);
  104.     }
  105.  
  106.     /* Use my own CCC and inherit screen white Pt */
  107.     bcopy ((char *)ccc, (char *)&myCCC, sizeof(XcmsCCCRec));
  108.     myCCC.clientWhitePt.format = XcmsUndefinedFormat; 
  109.     myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut comp func */
  110.  
  111.     while (hue_angle < 0.0) {
  112.     hue_angle += 360.0;
  113.     }
  114.     while (hue_angle >= 360.0) {
  115.     hue_angle -= 360.0;
  116.     } 
  117.  
  118.     hue = radians(hue_angle);
  119.     tmp.spec.CIELab.L_star = L_star;
  120.     tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, START_CHROMA);
  121.     tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, START_CHROMA);
  122.     tmp.pixel = pColor_return->pixel;
  123.     tmp.format = XcmsCIELabFormat;
  124.  
  125.     /* Step 1: compute the maximum L_star and chroma for this hue. */
  126.     bcopy((char *)&tmp, (char *)&max_lc, sizeof(XcmsColor));
  127.     if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved)
  128.     == XcmsFailure) {
  129.         return(XcmsFailure);
  130.     }
  131.  
  132.     /*
  133.      * Step 2:  Do a bisection here to compute the maximum chroma
  134.      *          Note the differences between when the point to be found
  135.      *          is above the maximum LC point and when it is below.
  136.      */
  137.     if (L_star <= max_lc.spec.CIELab.L_star) {
  138.     maxDist = max_lc.spec.CIELab.L_star;
  139.     } else {
  140.     maxDist = TOPL - max_lc.spec.CIELab.L_star;
  141.     }
  142.  
  143.     n_L_star = L_star;
  144.     last_L_star = -1.0;
  145.     nMaxCount = MAXBISECTCOUNT;
  146.     rFactor = 1.0;
  147.  
  148.     for (nCount = 0; nCount < nMaxCount; nCount++) {
  149.     prev_L_star =  last_L_star;
  150.     last_L_star =  tmp.spec.CIELab.L_star;
  151. /*    lastChroma = XCMS_CIELAB_PMETRIC_CHROMA(tmp.spec.CIELab.a_star,  */
  152. /*                        tmp.spec.CIELab.b_star); */
  153.     lastaStar = tmp.spec.CIELab.a_star;
  154.     lastbStar = tmp.spec.CIELab.b_star;
  155.     nT = (n_L_star - max_lc.spec.CIELab.L_star) / maxDist * rFactor;
  156.     if (nT > 0) {
  157.         tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT;
  158.         tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT;
  159.         tmp.spec.RGBi.blue  = rgb_saved.blue * (1.0 - nT) + nT;
  160.     } else {
  161.         tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT);
  162.         tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT);
  163.         tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT);
  164.     }
  165.     tmp.format = XcmsRGBiFormat;
  166.  
  167.     /* convert from RGB to CIELab */
  168.     if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp,
  169.                 ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat,
  170.                 (Bool *) NULL) == XcmsFailure) {
  171.         return(XcmsFailure);
  172.     }
  173.  
  174.     /*
  175.      * Now check if we've reached the target L_star
  176.      */
  177.     /* printf("result Lstar = %lf\n", tmp.spec.CIELab.L_star); */
  178.     if (tmp.spec.CIELab.L_star <= L_star + EPS &&
  179.         tmp.spec.CIELab.L_star >= L_star - EPS) {
  180.         bcopy((char *)&tmp, (char *)pColor_return, sizeof(XcmsColor));
  181.         return(XcmsSuccess);
  182.     }
  183.     if (nT > 0) {
  184.         n_L_star += ((TOPL - n_L_star) *
  185.              (L_star - tmp.spec.CIELab.L_star)) / (TOPL - L_star);
  186.     } else {
  187.         n_L_star *= L_star / tmp.spec.CIELuv.L_star;
  188.     }
  189.     if (tmp.spec.CIELab.L_star <= prev_L_star + EPS &&
  190.         tmp.spec.CIELab.L_star >= prev_L_star - EPS) {
  191.         rFactor *= 0.5;  /* selective relaxation employed */
  192.         /* printf("rFactor = %lf\n", rFactor); */
  193.     }
  194.     }
  195.     if (XCMS_FABS(last_L_star - L_star) < 
  196.     XCMS_FABS(tmp.spec.CIELab.L_star - L_star)) {
  197.         tmp.spec.CIELab.a_star = lastaStar;
  198.         tmp.spec.CIELab.b_star = lastbStar;
  199. /*        tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, lastChroma); */
  200. /*        tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, lastChroma); */
  201.     }
  202.     tmp.spec.CIELab.L_star = L_star;
  203.     bcopy((char *)&tmp, (char *)pColor_return, sizeof(XcmsColor));
  204.     return(XcmsSuccess);
  205. }
  206.