home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xcolored.zip / xcoloredit / color.c next >
C/C++ Source or Header  |  1991-06-18  |  5KB  |  286 lines

  1. /* $Header: /usr/nfs/maple/d0/users/rlh2/toolkit/installed-src/xcoloredit/RCS/color.c,v 1.2 90/06/30 14:32:48 rlh2 Rel Locker: rlh2 $ */
  2.  
  3. /* 
  4.  * color.c - color helper routines
  5.  * 
  6.  * Author:    Christopher A. Kent
  7.  *         Western Research Laboratory
  8.  *         Digital Equipment Corporation
  9.  * Date:    Sun Dec 13 1987
  10.  * Copyright (c) 1987 Christopher A. Kent
  11.  */
  12.  
  13. /* 
  14.  * See David F. Rogers, "Procedural Elements for Computer Graphics",
  15.  * McGraw-Hill, for the theory behind these routines.
  16.  */
  17.  
  18. /*
  19.  * $Log:    color.c,v $
  20.  * Revision 1.2  90/06/30  14:32:48  rlh2
  21.  * patchlevel 1
  22.  * 
  23.  * Revision 1.1  90/05/10  11:17:30  rlh2
  24.  * Initial revision
  25.  * 
  26.  * Revision 1.2  88/06/30  09:58:36  mikey
  27.  * Handles CMY also.
  28.  * 
  29.  * Revision 1.1  88/06/30  09:10:32  mikey
  30.  * Initial revision
  31.  * 
  32.  */
  33.  
  34. static char rcs_ident[] = "$Header: /usr/nfs/maple/d0/users/rlh2/toolkit/installed-src/xcoloredit/RCS/color.c,v 1.2 90/06/30 14:32:48 rlh2 Rel Locker: rlh2 $";
  35.  
  36. #include <X11/Xlib.h>
  37. #include "color.h"
  38.  
  39. #define    MAX_INTENSITY    65535                /* for X11 */
  40.  
  41. #define    MIN(a, b)   ((a)<(b)?(a):(b))
  42. #define    MAX(a, b)   ((a)>(b)?(a):(b))
  43. #define    ABS(x)        ((x)<0?-(x):(x))
  44.  
  45. RGB    RGBWhite = { MAX_INTENSITY, MAX_INTENSITY, MAX_INTENSITY };
  46. RGB    RGBBlack = { 0, 0, 0 };
  47.  
  48. /*
  49.  * Mix two RGBs, with scale factors alpha and beta, in RGB space.
  50.  */
  51.  
  52. RGB
  53. MixRGB(r, alpha, s, beta)
  54. RGB    r, s;
  55. float    alpha, beta;
  56. {
  57.     RGB    t;
  58.  
  59.     t.r = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.r) + beta*(s.r))));
  60.     t.g = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.g) + beta*(s.g))));
  61.     t.b = MAX(0, MIN(MAX_INTENSITY, (int)(alpha*(r.b) + beta*(s.b))));
  62.     return t;
  63. }
  64.  
  65. /*
  66.  * Mix two RGBs with scale factors alpha and beta, in HSV space.
  67.  */
  68.  
  69. RGB
  70. MixHSV(r, alpha, s, beta)
  71. RGB    r, s;
  72. float    alpha, beta;
  73. {
  74.     HSV    rr, ss, tt;
  75.  
  76.     rr = RGBToHSV(r);
  77.     ss = RGBToHSV(s);
  78.     tt.h = alpha*rr.h + beta*ss.h;
  79.     if (ABS(rr.h - ss.h) > 0.5) {
  80.         tt.h = tt.h + 0.5;
  81.         if (tt.h >= 1.0)
  82.             tt.h = tt.h - 1.0;
  83.     }
  84.     tt.s = alpha*rr.s + beta*ss.s;
  85.     tt.v = alpha*rr.v + beta*ss.v;
  86.     return HSVToRGB(tt);
  87. }
  88.  
  89. /*
  90.  * Convert an HSV to an RGB.
  91.  */
  92.  
  93. RGB
  94. HSVToRGB(hsv)
  95. HSV    hsv;
  96. {
  97.     RGB    rgb;
  98.     float    p, q, t, f;
  99.     int    i;
  100.     
  101.     if (hsv.s == 0.0)
  102.         rgb = PctToRGB(hsv.v, hsv.v, hsv.v);
  103.     else {
  104.         if (hsv.s > 1.0)
  105.             hsv.s = 1.0;
  106.         if (hsv.s < 0.0)
  107.             hsv.s = 0.0;
  108.         if (hsv.v > 1.0)
  109.             hsv.v = 1.0;
  110.         if (hsv.v < 0.0)
  111.             hsv.v = 0.0;
  112.         if (hsv.h >= 1.0)
  113.             hsv.h = 0.0;
  114.  
  115.         hsv.h = 6.0 * hsv.h;
  116.         i = (int) hsv.h;
  117.         f = hsv.h - (float) i;
  118.         p = hsv.v * (1.0 - hsv.s);
  119.         q = hsv.v * (1.0 - (hsv.s * f));
  120.         t = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
  121.  
  122.         switch(i) {
  123.         case 0:    rgb = PctToRGB(hsv.v, t, p); break;
  124.         case 1:    rgb = PctToRGB(q, hsv.v, p); break;
  125.         case 2:    rgb = PctToRGB(p, hsv.v, t); break;
  126.         case 3:    rgb = PctToRGB(p, q, hsv.v); break;
  127.         case 4:    rgb = PctToRGB(t, p, hsv.v); break;
  128.         case 5:    rgb = PctToRGB(hsv.v, p, q); break;
  129.         }
  130.     }
  131.     return rgb;
  132. }
  133.  
  134. /*
  135.  * Convert an RGB to HSV.
  136.  */
  137.  
  138. HSV
  139. RGBToHSV(rgb)
  140. RGB    rgb;
  141.  
  142. {
  143.     HSV    hsv;
  144.     float    rr, gg, bb;
  145.     float    min, max;
  146.     float    rc, gc, bc;
  147.     
  148.     rr = (float) rgb.r / (float) MAX_INTENSITY;
  149.     gg = (float) rgb.g / (float) MAX_INTENSITY;
  150.     bb = (float) rgb.b / (float) MAX_INTENSITY;
  151.     
  152.     max = MAX(MAX(rr, gg), bb);
  153.     min = MIN(MIN(rr, gg), bb);
  154.     hsv.v = max;
  155.     if (max == 0.0)
  156.         hsv.s = 0.0;
  157.     else
  158.         hsv.s = (max - min) / max;
  159.     if (hsv.s == 0.0)
  160.         hsv.h = 0.0;
  161.     else {
  162.         rc = (max - rr) / (max - min);
  163.         gc = (max - gg) / (max - min);
  164.         bc = (max - bb) / (max - min);
  165.         if (rr == max)
  166.             hsv.h = bc - gc;
  167.         else if (gg == max)
  168.             hsv.h = 2.0 + rc - bc;
  169.         else if (bb = max)
  170.             hsv.h = 4.0 + gc - rc;
  171.  
  172.         if (hsv.h < 0.0)
  173.             hsv.h += 6.0;
  174.         hsv.h = hsv.h / 6.0;
  175.     }
  176.     return hsv;
  177. }
  178.  
  179. /*
  180.  * Intensity percentages to RGB.
  181.  */
  182.  
  183. RGB
  184. PctToRGB(rr, gg, bb)
  185. float    rr, gg, bb;
  186. {
  187.     RGB    rgb;
  188.     
  189.     if (rr > 1.0)
  190.         rr = 1.0;
  191.     if (gg > 1.0)
  192.         gg = 1.0;
  193.     if (bb > 1.0)
  194.         bb = 1.0;
  195.     
  196.     rgb.r = (int)(0.5 + rr * MAX_INTENSITY);
  197.     rgb.g = (int)(0.5 + gg * MAX_INTENSITY);
  198.     rgb.b = (int)(0.5 + bb * MAX_INTENSITY);
  199.     return rgb;
  200. }
  201.  
  202. /*
  203.  * Intensity percentages to HSV.
  204.  */
  205.  
  206. HSV
  207. PctToHSV(hh, ss, vv)
  208. float    hh, ss, vv;
  209. {
  210.     HSV    hsv;
  211.  
  212.     if (hh > 1.0)
  213.         hh = 1.0;
  214.     if (ss > 1.0)
  215.         ss = 1.0;
  216.     if (vv > 1.0)
  217.         vv = 1.0;
  218.  
  219.     hsv.h = hh;
  220.     hsv.s = ss;
  221.     hsv.v = vv;
  222.     return hsv;
  223. }
  224.  
  225. /*
  226.  * The Manhattan distance between two colors, between 0.0 and 3.0.
  227.  */
  228.  
  229. float
  230. RGBDist(r, s)
  231. RGB    r, s;
  232. {
  233.     return (
  234.         ABS((float)(r.r - s.r)) +
  235.         ABS((float)(r.g - s.g)) +
  236.         ABS((float)(r.b - s.b))) / (float)MAX_INTENSITY;
  237. }
  238.  
  239. /*
  240.  * Load an XColor with an RGB.
  241.  */
  242.  
  243. RGBToXColor(r, x)
  244. RGB    r;
  245. XColor    *x;
  246. {
  247.     x->red = r.r;
  248.     x->green = r.g;
  249.     x->blue = r.b;
  250.     x->flags = DoRed | DoGreen | DoBlue;
  251. }
  252.  
  253. /*
  254.  * Convert a CMY to RGB.
  255.  */
  256.  
  257. RGB
  258. CMYToRGB(cmy)
  259. CMY    cmy;
  260.  
  261. {
  262.     RGB    rgb;
  263.  
  264.     rgb.r = MAX_INTENSITY - cmy.c;
  265.     rgb.g = MAX_INTENSITY - cmy.m;
  266.     rgb.b = MAX_INTENSITY - cmy.y;
  267.     return rgb;
  268. }
  269.  
  270. /*
  271.  * Convert an RGB to CMY.
  272.  */
  273.  
  274. CMY
  275. RGBToCMY(rgb)
  276. RGB    rgb;
  277.  
  278. {
  279.     CMY    cmy;
  280.  
  281.     cmy.c = MAX_INTENSITY - rgb.r;
  282.     cmy.m = MAX_INTENSITY - rgb.g;
  283.     cmy.y = MAX_INTENSITY - rgb.b;
  284.     return cmy;
  285. }
  286.