Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.8 KiB

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