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

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