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

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