color2.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 7k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*  COLOR2.C
  2. **
  3. **  Copyright (C) Microsoft, 1993, All Rights Reserved.
  4. **
  5. **
  6. **  History:
  7. **
  8. */
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. int H,L,S;                         /* Hue, Lightness, Saturation */
  12. #define  RANGE   240                 /* range of values for HLS scrollbars */
  13.                                      /* HLS-RGB conversions work best when
  14.                                         RANGE is divisible by 6 */
  15. #define  HLSMAX   RANGE
  16. #define  RGBMAX   255
  17. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  18. /* Color conversion routines --
  19.    RGBtoHLS() takes a DWORD RGB value, translates it to HLS, and stores the
  20.    results in the global vars H, L, and S.  HLStoRGB takes the current values
  21.    of H, L, and S and returns the equivalent value in an RGB DWORD.  The vars
  22.    H, L and S are written to only by 1) RGBtoHLS (initialization) or 2) the
  23.    scrollbar handlers.
  24.    A point of reference for the algorithms is Foley and Van Dam, pp. 618-19.
  25.    Their algorithm is in floating point.  CHART implements a less general
  26.    (hardwired ranges) integral algorithm.
  27. */
  28. /* There are potential roundoff errors lurking throughout here.
  29.    (0.5 + x/y) without floating point,
  30.       (x/y) phrased ((x + (y/2))/y)
  31.    yields very small roundoff error.
  32.    This makes many of the following divisions look funny.
  33. */
  34.                         /* H,L, and S vary over 0-HLSMAX */
  35.                         /* R,G, and B vary over 0-RGBMAX */
  36.                         /* HLSMAX BEST IF DIVISIBLE BY 6 */
  37.                         /* RGBMAX, HLSMAX must each fit in a byte. */
  38. #define UNDEFINED (HLSMAX*2/3)/* Hue is undefined if Saturation is 0 (grey-scale) */
  39.                            /* This value determines where the Hue scrollbar is */
  40.                            /* initially set for achromatic colors */
  41. void   RGBtoHLS(DWORD lRGBColor)
  42. {
  43.    int R,G,B;                /* input RGB values */
  44.    WORD cMax,cMin;        /* max and min RGB values */
  45.    WORD cSum,cDif;
  46.    int  Rdelta,Gdelta,Bdelta;  /* intermediate value: % of spread from max */
  47.    /* get R, G, and B out of DWORD */
  48.    R = GetRValue(lRGBColor);
  49.    G = GetGValue(lRGBColor);
  50.    B = GetBValue(lRGBColor);
  51.    /* calculate lightness */
  52.    cMax = max( max(R,G), B);
  53.    cMin = min( min(R,G), B);
  54.    cSum = cMax + cMin;
  55.    L = (WORD)(((cSum * (DWORD)HLSMAX) + RGBMAX )/(2*RGBMAX));
  56.    cDif = cMax - cMin;
  57.    if (!cDif)    /* r=g=b --> achromatic case */
  58.      {
  59.        S = 0;                         /* saturation */
  60.        H = UNDEFINED;                 /* hue */
  61.      }
  62.    else                           /* chromatic case */
  63.      {
  64.        /* saturation */
  65.        if (L <= (HLSMAX/2))
  66.            S = (WORD) (((cDif * (DWORD) HLSMAX) + (cSum / 2) ) / cSum);
  67.        else
  68.            S = (WORD) ((DWORD) ((cDif * (DWORD) HLSMAX) + (DWORD)((2*RGBMAX-cSum)/2) )
  69.                                                  / (2*RGBMAX-cSum));
  70.       /* hue */
  71.       Rdelta = (int) (( ((cMax-R)*(DWORD)(HLSMAX/6)) + (cDif / 2) ) / cDif);
  72.       Gdelta = (int) (( ((cMax-G)*(DWORD)(HLSMAX/6)) + (cDif / 2) ) / cDif);
  73.       Bdelta = (int) (( ((cMax-B)*(DWORD)(HLSMAX/6)) + (cDif / 2) ) / cDif);
  74.       if ((WORD) R == cMax)
  75.          H = Bdelta - Gdelta;
  76.       else if ((WORD) G == cMax)
  77.          H = (HLSMAX/3) + Rdelta - Bdelta;
  78.       else /* B == cMax */
  79.          H = ((2*HLSMAX)/3) + Gdelta - Rdelta;
  80.       if (H < 0)
  81.          H += HLSMAX;
  82.       if (H > HLSMAX)
  83.          H -= HLSMAX;
  84.    }
  85. }
  86. /* utility routine for HLStoRGB */
  87. WORD NEAR PASCAL HueToRGB(WORD n1, WORD n2, WORD hue)
  88. {
  89.    /* range check: note values passed add/subtract thirds of range */
  90.    /* The following is redundant for WORD (unsigned int) */
  91. #if 0
  92.    if (hue < 0)
  93.       hue += HLSMAX;
  94. #endif
  95.    if (hue > HLSMAX)
  96.       hue -= HLSMAX;
  97.    /* return r,g, or b value from this tridrant */
  98.    if (hue < (HLSMAX/6))
  99.       return ( n1 + (((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)) );
  100.    if (hue < (HLSMAX/2))
  101.       return ( n2 );
  102.    if (hue < ((HLSMAX*2)/3))
  103.       return ( n1 + (((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12)) / (HLSMAX/6)) );
  104.    else
  105.       return ( n1 );
  106. }
  107. DWORD NEAR PASCAL HLStoRGB(WORD hue, WORD lum, WORD sat)
  108. {
  109.   WORD R,G,B;                      /* RGB component values */
  110.   WORD  Magic1,Magic2;       /* calculated magic numbers (really!) */
  111.   if (sat == 0)                /* achromatic case */
  112.     {
  113.       R = G = B = (lum * RGBMAX) / HLSMAX;
  114.       if (hue != UNDEFINED)
  115.         {
  116.          /* ERROR */
  117.         }
  118.     }
  119.   else                         /* chromatic case */
  120.     {
  121.       /* set up magic numbers */
  122.       if (lum <= (HLSMAX/2))
  123.           Magic2 = (WORD)((lum * ((DWORD)HLSMAX + sat) + (HLSMAX/2))/HLSMAX);
  124.       else
  125.           Magic2 = lum + sat - (WORD)(((lum*sat) + (DWORD)(HLSMAX/2))/HLSMAX);
  126.       Magic1 = 2*lum-Magic2;
  127.       /* get RGB, change units from HLSMAX to RGBMAX */
  128.       R = (WORD)((HueToRGB(Magic1,Magic2,(WORD)(hue+(WORD)(HLSMAX/3)))*(DWORD)RGBMAX + (HLSMAX/2))) / (WORD)HLSMAX;
  129.       G = (WORD)((HueToRGB(Magic1,Magic2,hue)*(DWORD)RGBMAX + (HLSMAX/2))) / HLSMAX;
  130.       B = (WORD)((HueToRGB(Magic1,Magic2,(WORD)(hue-(WORD)(HLSMAX/3)))*(DWORD)RGBMAX + (HLSMAX/2))) / (WORD)HLSMAX;
  131.     }
  132.   return(RGB(R,G,B));
  133. }
  134. DWORD  DarkenColor(DWORD rgb, int n)
  135. {
  136.     RGBtoHLS(rgb);
  137.     return HLStoRGB((WORD)H, (WORD)((long)L * n / 1000), (WORD)S);
  138. }
  139. DWORD  BrightenColor(DWORD rgb, int n)
  140. {
  141.     RGBtoHLS(rgb);
  142.     return HLStoRGB((WORD)H, (WORD)(((long)L * (1000-n) + (RANGE+1l)*n) / 1000), (WORD)S);
  143. }
  144. #ifdef OLDCODE
  145. void  Get3DColors(DWORD rgbFace, LPDWORD lprgbShadow, LPDWORD lprgbHilight)
  146. {
  147.     RGBtoHLS(rgbFace);
  148.     // colors are half way between the face and the min/max values
  149.     *lprgbShadow  = HLStoRGB(H, L * 2 / 3, S);
  150.     *lprgbHilight = HLStoRGB(H, (L + RANGE + 1) / 2, S);
  151.     *lprgbHilight = HLStoRGB(H, (L + RANGE + 1) / 2, S);
  152. //    *lprgbHilight = HLStoRGB(H, MIN(RANGE, L * 7 / 6), S);
  153. }
  154. #endif
  155. DWORD FAR PASCAL AdjustLuma(DWORD rgb, int n, BOOL fScale)
  156. {
  157.     if (n == 0)
  158.         return rgb;
  159.     RGBtoHLS(rgb);
  160.     if (fScale)
  161.     {
  162.         if (n > 0)
  163.         {
  164.             return HLStoRGB((WORD)H, (WORD)(((long)L * (1000 - n) + (RANGE + 1l) * n) / 1000), (WORD)S);
  165.         }
  166.         else
  167.         {
  168.             return HLStoRGB((WORD)H, (WORD)(((long)L * (n + 1000)) / 1000), (WORD)S);
  169.         }
  170.     }
  171.     L += (int)((long)n * RANGE / 1000);
  172.     if (L < 0)
  173.         L = 0;
  174.     if (L > HLSMAX)
  175.         L = HLSMAX;
  176.     return HLStoRGB((WORD)H, (WORD)L, (WORD)S);
  177. }