home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / Xcms_Luv.c < prev    next >
C/C++ Source or Header  |  1999-11-02  |  10KB  |  391 lines

  1. /* $XConsortium: Luv.c,v 1.13 93/09/07 21:31:42 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.  *    NAME
  28.  *        CIELuv.c
  29.  *
  30.  *    DESCRIPTION
  31.  *        This file contains routines that support the CIE L*u*v*
  32.  *        color space to include conversions to and from the CIE
  33.  *        XYZ space.
  34.  *
  35.  *    DOCUMENTATION
  36.  *        "TekColor Color Management System, System Implementor's Manual"
  37.  *        and
  38.  *        Fred W. Billmeyer & Max Saltzman, "Principles of Color
  39.  *        Technology", John Wily & Sons, Inc, 1981.
  40.  */
  41.  
  42. #include "Xlib_private.h"
  43. #include <X11/Xos.h>
  44. #include "Xcmsint.h"
  45.  
  46. /*
  47.  *    EXTERNS
  48.  */
  49.  
  50. extern char _XcmsCIELuv_prefix[];
  51.  
  52.  
  53. /*
  54.  *    FORWARD DECLARATIONS
  55.  */
  56.  
  57. static int CIELuv_ParseString();
  58. static Status XcmsCIELuv_ValidSpec();
  59.  
  60. /*
  61.  *    DEFINES
  62.  *        Internal definitions that need NOT be exported to any package
  63.  *        or program using this package.
  64.  */
  65. #ifdef DBL_EPSILON
  66. #  define XMY_DBL_EPSILON DBL_EPSILON
  67. #else
  68. #  define XMY_DBL_EPSILON 0.00001
  69. #endif
  70.  
  71.  
  72. /*
  73.  *    LOCAL VARIABLES
  74.  */
  75.  
  76.     /*
  77.      * NULL terminated list of functions applied to get from CIELuv to CIEXYZ
  78.      */
  79. static XcmsConversionProc Fl_CIELuv_to_CIEXYZ[] = {
  80.     XcmsCIELuvToCIEuvY,
  81.     XcmsCIEuvYToCIEXYZ,
  82.     NULL
  83. };
  84.  
  85.     /*
  86.      * NULL terminated list of functions applied to get from CIEXYZ to CIELuv
  87.      */
  88. static XcmsConversionProc Fl_CIEXYZ_to_CIELuv[] = {
  89.     XcmsCIEXYZToCIEuvY,
  90.     XcmsCIEuvYToCIELuv,
  91.     NULL
  92. };
  93.  
  94. /*
  95.  *    GLOBALS
  96.  */
  97.  
  98.     /*
  99.      * CIE Luv Color Space
  100.      */
  101. XcmsColorSpace    XcmsCIELuvColorSpace =
  102.     {
  103.     _XcmsCIELuv_prefix,    /* prefix */
  104.     XcmsCIELuvFormat,        /* id */
  105.     CIELuv_ParseString,    /* parseString */
  106.     Fl_CIELuv_to_CIEXYZ,    /* to_CIEXYZ */
  107.     Fl_CIEXYZ_to_CIELuv,    /* from_CIEXYZ */
  108.     1
  109.     };
  110.  
  111.  
  112. /************************************************************************
  113.  *                                    *
  114.  *             PRIVATE ROUTINES                *
  115.  *                                    *
  116.  ************************************************************************/
  117.  
  118. /*
  119.  *    NAME
  120.  *        CIELuv_ParseString
  121.  *
  122.  *    SYNOPSIS
  123.  */
  124. static int
  125. CIELuv_ParseString(spec, pColor)
  126.     register char *spec;
  127.     XcmsColor *pColor;
  128. /*
  129.  *    DESCRIPTION
  130.  *        This routines takes a string and attempts to convert
  131.  *        it into a XcmsColor structure with XcmsCIELuvFormat.
  132.  *        The assumed CIELuv string syntax is:
  133.  *            CIELuv:<L>/<u>/<v>
  134.  *        Where L, u, and v are in string input format for floats
  135.  *        consisting of:
  136.  *            a. an optional sign
  137.  *            b. a string of numbers possibly containing a decimal point,
  138.  *            c. an optional exponent field containing an 'E' or 'e'
  139.  *            followed by a possibly signed integer string.
  140.  *
  141.  *    RETURNS
  142.  *        0 if failed, non-zero otherwise.
  143.  */
  144. {
  145.     DBUG_ENTER("CIELuv_ParseString")
  146.     int n;
  147.     char *pchar;
  148.  
  149.     if ((pchar = strchr(spec, ':')) == NULL) {
  150.     DBUG_RETURN(XcmsFailure);
  151.     }
  152.     n = (int)(pchar - spec);
  153.  
  154.     /*
  155.      * Check for proper prefix.
  156.      */
  157.     if (strncmp(spec, _XcmsCIELuv_prefix, n) != 0) {
  158.     DBUG_RETURN(XcmsFailure);
  159.     }
  160.  
  161.     /*
  162.      * Attempt to parse the value portion.
  163.      */
  164.     if (sscanf(spec + n + 1, "%lf/%lf/%lf",
  165.         &pColor->spec.CIELuv.L_star,
  166.         &pColor->spec.CIELuv.u_star,
  167.         &pColor->spec.CIELuv.v_star) != 3) {
  168.     DBUG_RETURN(XcmsFailure);
  169.     }
  170.     pColor->format = XcmsCIELuvFormat;
  171.     pColor->pixel = 0;
  172.     n = XcmsCIELuv_ValidSpec(pColor);
  173.     DBUG_RETURN(n);
  174. }
  175.  
  176.  
  177. /************************************************************************
  178.  *                                    *
  179.  *             PUBLIC ROUTINES                *
  180.  *                                    *
  181.  ************************************************************************/
  182.  
  183. /*
  184.  *    NAME
  185.  *        XcmsCIELuv_ValidSpec
  186.  *
  187.  *    SYNOPSIS
  188.  */
  189. static Status
  190. XcmsCIELuv_ValidSpec(pColor)
  191.     XcmsColor *pColor;
  192. /*
  193.  *    DESCRIPTION
  194.  *        Checks if color specification valid for CIE L*u*v*.
  195.  *
  196.  *    RETURNS
  197.  *        XcmsFailure if invalid,
  198.  *        XcmsSuccess if valid.
  199.  *
  200.  */
  201. {
  202.     DBUG_ENTER("XcmsCIELuv_ValidSpec")
  203.     if (pColor->format != XcmsCIELuvFormat
  204.         ||
  205.         (pColor->spec.CIELuv.L_star < 0.0 - XMY_DBL_EPSILON)
  206.         ||
  207.         (pColor->spec.CIELuv.L_star > 100.0 + XMY_DBL_EPSILON)) {
  208.     DBUG_RETURN(XcmsFailure);
  209.     }
  210.     DBUG_RETURN(XcmsSuccess);
  211. }
  212.  
  213.  
  214. /*
  215.  *    NAME
  216.  *        XcmsCIELuvToCIEuvY - convert CIELuv to CIEuvY
  217.  *
  218.  *    SYNOPSIS
  219.  */
  220. Status
  221. XcmsCIELuvToCIEuvY(ccc, pLuv_WhitePt, pColors_in_out, nColors)
  222.     XcmsCCC ccc;
  223.     XcmsColor *pLuv_WhitePt;
  224.     XcmsColor *pColors_in_out;
  225.     unsigned int nColors;
  226. /*
  227.  *    DESCRIPTION
  228.  *        Converts color specifications in an array of XcmsColor
  229.  *        structures from CIELuv format to CIEuvY format.
  230.  *
  231.  *    RETURNS
  232.  *        XcmsFailure if failed,
  233.  *        XcmsSuccess if succeeded.
  234.  *
  235.  */
  236. {
  237.     DBUG_ENTER("XcmsCIELuvToCIEuvY")
  238.     XcmsColor    *pColor = pColors_in_out;
  239.     XcmsColor    whitePt;
  240.     XcmsCIEuvY    uvY_return;
  241.     XcmsFloat    tmpVal;
  242.     register int i;
  243.  
  244.     /*
  245.      * Check arguments
  246.      */
  247.     if (pLuv_WhitePt == NULL || pColors_in_out == NULL) {
  248.     DBUG_RETURN(XcmsFailure);
  249.     }
  250.  
  251.     /*
  252.      * Make sure white point is in CIEuvY form
  253.      */
  254.     if (pLuv_WhitePt->format != XcmsCIEuvYFormat) {
  255.     /* Make copy of the white point because we're going to modify it */
  256.     memcpy((char *)&whitePt, (char *)pLuv_WhitePt, sizeof(XcmsColor));
  257.     if (!_XcmsDIConvertColors(ccc, &whitePt, (XcmsColor *)NULL,
  258.         1, XcmsCIEuvYFormat)) {
  259.         DBUG_RETURN(XcmsFailure);
  260.     }
  261.     pLuv_WhitePt = &whitePt;
  262.     }
  263.     /* Make sure it is a white point, i.e., Y == 1.0 */
  264.     if (pLuv_WhitePt->spec.CIEuvY.Y != 1.0) {
  265.     DBUG_RETURN(XcmsFailure);
  266.     }
  267.  
  268.     /*
  269.      * Now convert each XcmsColor structure to CIEXYZ form
  270.      */
  271.     for (i = 0; i < nColors; i++, pColor++) {
  272.  
  273.     /* Make sure original format is CIELuv and is valid */
  274.     if (!XcmsCIELuv_ValidSpec(pColor)) {
  275.         DBUG_RETURN(XcmsFailure);
  276.     }
  277.  
  278.     if (pColor->spec.CIELuv.L_star < 7.99953624) {
  279.         uvY_return.Y = pColor->spec.CIELuv.L_star / 903.29;
  280.     } else {
  281.         tmpVal = (pColor->spec.CIELuv.L_star + 16.0) / 116.0;
  282.         uvY_return.Y = tmpVal * tmpVal * tmpVal; /* tmpVal ** 3 */
  283.     }
  284.  
  285.  
  286.  
  287.     if (pColor->spec.CIELuv.L_star == 0.0) {
  288.         uvY_return.u_prime = pLuv_WhitePt->spec.CIEuvY.u_prime;
  289.         uvY_return.v_prime = pLuv_WhitePt->spec.CIEuvY.v_prime;
  290.     } else {
  291.         tmpVal = 13.0 * (pColor->spec.CIELuv.L_star / 100.0);
  292.         uvY_return.u_prime = pColor->spec.CIELuv.u_star/tmpVal + 
  293.                 pLuv_WhitePt->spec.CIEuvY.u_prime;
  294.         uvY_return.v_prime = pColor->spec.CIELuv.v_star/tmpVal +
  295.                 pLuv_WhitePt->spec.CIEuvY.v_prime;
  296.     }
  297.     /* Copy result to pColor */
  298.     memcpy((char *)&pColor->spec, (char *)&uvY_return, sizeof(XcmsCIEuvY));
  299.  
  300.     /* Identify that the format is now CIEuvY */
  301.     pColor->format = XcmsCIEuvYFormat;
  302.     }
  303.     DBUG_RETURN(XcmsSuccess);
  304. }
  305.  
  306.  
  307. /*
  308.  *    NAME
  309.  *        XcmsCIEuvYToCIELuv - convert CIEuvY to CIELuv
  310.  *
  311.  *    SYNOPSIS
  312.  */
  313. Status
  314. XcmsCIEuvYToCIELuv(ccc, pLuv_WhitePt, pColors_in_out, nColors)
  315.     XcmsCCC ccc;
  316.     XcmsColor *pLuv_WhitePt;
  317.     XcmsColor *pColors_in_out;
  318.     unsigned int nColors;
  319. /*
  320.  *    DESCRIPTION
  321.  *        Converts color specifications in an array of XcmsColor
  322.  *        structures from CIEuvY format to CIELab format.
  323.  *
  324.  *    RETURNS
  325.  *        XcmsFailure if failed,
  326.  *        XcmsSuccess if succeeded.
  327.  *
  328.  */
  329. {
  330.     DBUG_ENTER("XcmsCIEuvYToCIELuv")
  331.     XcmsColor    *pColor = pColors_in_out;
  332.     XcmsColor    whitePt;
  333.     XcmsCIELuv    Luv_return;
  334.     XcmsFloat    tmpVal;
  335.     register int i;
  336.  
  337.     /*
  338.      * Check arguments
  339.      */
  340.     if (pLuv_WhitePt == NULL || pColors_in_out == NULL) {
  341.     DBUG_RETURN(XcmsFailure);
  342.     }
  343.  
  344.     /*
  345.      * Make sure white point is in CIEuvY form
  346.      */
  347.     if (pLuv_WhitePt->format != XcmsCIEuvYFormat) {
  348.     /* Make copy of the white point because we're going to modify it */
  349.     memcpy((char *)&whitePt, (char *)pLuv_WhitePt, sizeof(XcmsColor));
  350.     if (!_XcmsDIConvertColors(ccc, &whitePt,
  351.         (XcmsColor *)NULL, 1, XcmsCIEuvYFormat)) {
  352.         DBUG_RETURN(XcmsFailure);
  353.     }
  354.     pLuv_WhitePt = &whitePt;
  355.     }
  356.     /* Make sure it is a white point, i.e., Y == 1.0 */
  357.     if (pLuv_WhitePt->spec.CIEuvY.Y != 1.0) {
  358.     DBUG_RETURN(XcmsFailure);
  359.     }
  360.  
  361.     /*
  362.      * Now convert each XcmsColor structure to CIEXYZ form
  363.      */
  364.     for (i = 0; i < nColors; i++, pColor++) {
  365.  
  366.     if (!_XcmsCIEuvY_ValidSpec(pColor)) {
  367.         DBUG_RETURN(XcmsFailure);
  368.     }
  369.  
  370.     /* Now convert the uvY to Luv */
  371.     Luv_return.L_star = 
  372.         (pColor->spec.CIEuvY.Y < 0.008856)
  373.         ?
  374.         (pColor->spec.CIEuvY.Y * 903.29)
  375.         :
  376.         ((XcmsFloat)(XCMS_CUBEROOT(pColor->spec.CIEuvY.Y) * 116.0) - 16.0);
  377.     tmpVal = 13.0 * (Luv_return.L_star / 100.0);
  378.     Luv_return.u_star = tmpVal *
  379.        (pColor->spec.CIEuvY.u_prime - pLuv_WhitePt->spec.CIEuvY.u_prime);
  380.     Luv_return.v_star = tmpVal *
  381.        (pColor->spec.CIEuvY.v_prime - pLuv_WhitePt->spec.CIEuvY.v_prime);
  382.  
  383.     /* Copy result to pColor */
  384.     memcpy((char *)&pColor->spec, (char *)&Luv_return, sizeof(XcmsCIELuv));
  385.  
  386.     /* Identify that the format is now CIEuvY */
  387.     pColor->format = XcmsCIELuvFormat;
  388.     }
  389.     DBUG_RETURN(XcmsSuccess);
  390. }
  391.