00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
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
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
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
00117
00118 delta = max - min;
00119 if (max > 0.0)
00120 *sat = delta / max;
00121 else
00122 *sat = 0.0;
00123
00124
00125
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
00140
00141 *hue *= 60.0;
00142 if (*hue < 0.0)
00143 *hue += 360.0;
00144 }
00145 }
00146
00147
00148
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)
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
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
00256
00257
00258
00259
00260
00261
00262