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

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