color.c

Go to the documentation of this file.
00001 /*                         C O L O R . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1997-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** \addtogroup color */
00023 /*@{*/
00024 /** @file color.c
00025  *  Routines to convert between various color models.
00026  *
00027  *  @author
00028  *      Paul Tanenbaum
00029  *
00030  *  @par Source
00031  *      The U. S. Army Research Laboratory                      @n
00032  *      Aberdeen Proving Ground, Maryland  21005-5068  USA
00033  *
00034  *
00035  *              Convert between RGB and HSV color models
00036  *
00037  *      R, G, and B are in {0, 1, ..., 255},
00038  *
00039  *      H is in [0.0, 360.0), and S and V are in [0.0, 1.0],
00040  *
00041  *      unless S = 0.0, in which case H = ACHROMATIC.
00042  *
00043  *      These two routines are adapted from:
00044  *      pp. 592-3 of J.D. Foley, A. van Dam, S.K. Feiner, and J.F. Hughes,
00045  *      _Computer graphics: principles and practice_, 2nd ed., Addison-Wesley,
00046  *      Reading, MA, 1990.
00047  */
00048 
00049 static const char libbu_color_RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/libbu/color.c,v 14.16 2006/08/31 05:50:24 lbutler Exp $ (BRL)";
00050 
00051 #include "common.h"
00052 
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055 #include <math.h>
00056 #include <ctype.h>
00057 #ifdef HAVE_STRING_H
00058 #  include <string.h>
00059 #else
00060 #  include <strings.h>
00061 #endif
00062 #if defined(HAVE_STDARG_H)
00063 #  include <stdarg.h>
00064 #endif
00065 
00066 #include "machine.h"
00067 #include "bu.h"
00068 #include "vmath.h"
00069 
00070 
00071 
00072 #define ACHROMATIC      -1.0
00073 
00074 #define HUE     0
00075 #define SAT     1
00076 #define VAL     2
00077 
00078 #define RED     0
00079 #define GRN     1
00080 #define BLU     2
00081 
00082 
00083 /**
00084  *                      B U _ R G B _ T O _ H S V
00085  *
00086  */
00087 void bu_rgb_to_hsv (unsigned char *rgb, fastf_t *hsv)
00088 {
00089     fastf_t     red, grn, blu;
00090     fastf_t     *hue = &hsv[HUE];
00091     fastf_t     *sat = &hsv[SAT];
00092     fastf_t     *val = &hsv[VAL];
00093     fastf_t     max, min;
00094     fastf_t     delta;
00095 
00096     /*
00097      *  Compute value
00098      */
00099     max = min = red = ((fastf_t) rgb[RED]) / 255.0;
00100 
00101     grn = ((fastf_t) rgb[GRN]) / 255.0;
00102     if (grn < min)
00103         min = grn;
00104     else if (grn > max)
00105         max = grn;
00106 
00107     blu = ((fastf_t) rgb[BLU]) / 255.0;
00108     if (blu < min)
00109         min = blu;
00110     else if (blu > max)
00111         max = blu;
00112 
00113     *val = max;
00114 
00115     /*
00116      *  Compute saturation
00117      */
00118     delta = max - min;
00119     if (max > 0.0)
00120         *sat = delta / max;
00121     else
00122         *sat = 0.0;
00123 
00124     /*
00125      *  Compute hue
00126      */
00127     if (*sat == 0.0)
00128         *hue = ACHROMATIC;
00129     else
00130     {
00131         if (red == max)
00132             *hue = (grn - blu) / delta;
00133         else if (grn == max)
00134             *hue = 2.0 + (blu - red) / delta;
00135         else if (blu == max)
00136             *hue = 4.0 + (red - grn) / delta;
00137 
00138         /*
00139          *      Convert hue to degrees
00140          */
00141         *hue *= 60.0;
00142         if (*hue < 0.0)
00143             *hue += 360.0;
00144     }
00145 }
00146 
00147 /**
00148  *                      B U _ H S V _ T O _ R G B
00149  *
00150  */
00151 int bu_hsv_to_rgb (fastf_t *hsv, unsigned char *rgb)
00152 {
00153     fastf_t     float_rgb[3];
00154     fastf_t     hue, sat, val;
00155     fastf_t     hue_frac;
00156     fastf_t     p, q, t;
00157     int         hue_int;
00158 
00159     hue = hsv[HUE];
00160     sat = hsv[SAT];
00161     val = hsv[VAL];
00162 
00163     if ((((hue < 0.0) || (hue > 360.0)) && (hue != ACHROMATIC))
00164      || (sat < 0.0) || (sat > 1.0)
00165      || (val < 0.0) || (val > 1.0)
00166      || ((hue == ACHROMATIC) && (sat > 0.0)))
00167     {
00168         bu_log("bu_hsv_to_rgb: Illegal HSV (%g, %g, %g)\n",
00169             V3ARGS(hsv));
00170         return (0);
00171     }
00172     if (sat == 0.0)     /*      so hue == ACHROMATIC (or is ignored)    */
00173         VSETALL(float_rgb, val)
00174     else
00175     {
00176         if (hue == 360.0)
00177             hue = 0.0;
00178         hue /= 60.0;
00179         hue_int = floor((double) hue);
00180         hue_frac = hue - hue_int;
00181         p = val * (1.0 - sat);
00182         q = val * (1.0 - (sat * hue_frac));
00183         t = val * (1.0 - (sat * (1.0 - hue_frac)));
00184         switch (hue_int)
00185         {
00186             case 0: VSET(float_rgb, val, t, p); break;
00187             case 1: VSET(float_rgb, q, val, p); break;
00188             case 2: VSET(float_rgb, p, val, t); break;
00189             case 3: VSET(float_rgb, p, q, val); break;
00190             case 4: VSET(float_rgb, t, p, val); break;
00191             case 5: VSET(float_rgb, val, p, q); break;
00192             default:
00193                 bu_log("%s:%d: This shouldn't happen\n",
00194                     __FILE__, __LINE__);
00195                 bu_bomb("unexpected condition encountered in bu_hsv_to_rgb\n");
00196         }
00197     }
00198 
00199     rgb[RED] = float_rgb[RED] * 255;
00200     rgb[GRN] = float_rgb[GRN] * 255;
00201     rgb[BLU] = float_rgb[BLU] * 255;
00202 
00203     return (1);
00204 }
00205 
00206 /**
00207  *                      B U _ S T R _ T O _ R G B
00208  *
00209  */
00210 int bu_str_to_rgb (char *str, unsigned char *rgb)
00211 {
00212     int num;
00213     int r, g, b;
00214 
00215     r = g = b = -1;
00216     while (isspace(*str))
00217         ++str;
00218 
00219     if (*str == '#')
00220     {
00221         if (strlen(++str) != 6)
00222             return 0;
00223         num = sscanf(str, "%02x%02x%02x", (unsigned int *)&r, (unsigned int *)&g, (unsigned int *)&b);
00224 #if 0
00225         bu_log("# notation: I read %d of %d, %d, %d\n", num, r, g, b);
00226 #endif
00227     }
00228     else if (isdigit(*str))
00229     {
00230         num = sscanf(str, "%d/%d/%d", &r, &g, &b);
00231 #if 0
00232         bu_log("slash separation: I read %d of %d, %d, %d\n", num, r, g, b);
00233 #endif
00234         if (num == 1)
00235         {
00236             num = sscanf(str, "%d %d %d", &r, &g, &b);
00237 #if 0
00238             bu_log("blank separation: I read %d of %d, %d, %d\n", num, r, g, b);
00239 #endif
00240         }
00241         VSET(rgb, r, g, b);
00242         if ((r < 0) || (r > 255)
00243          || (g < 0) || (g > 255)
00244          || (b < 0) || (b > 255))
00245             return 0;
00246     }
00247     else
00248         return 0;
00249 
00250     VSET(rgb, r, g, b);
00251     return 1;
00252 }
00253 /*@}*/
00254 /*
00255  * Local Variables:
00256  * mode: C
00257  * tab-width: 8
00258  * c-basic-offset: 4
00259  * indent-tabs-mode: t
00260  * End:
00261  * ex: shiftwidth=4 tabstop=8
00262  */

Generated on Mon Sep 18 01:24:47 2006 for BRL-CAD by  doxygen 1.4.6