RenderEngine.1.HLSColor.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. using System;
  2. using System.Drawing;
  3. namespace Microsoft.Windows.Forms
  4. {
  5. public static partial class RenderEngine
  6. {
  7. /// <summary>
  8. /// 色调,亮度,饱和度颜色
  9. /// </summary>
  10. private struct HLSColor
  11. {
  12. private const int ShadowAdj = -333;
  13. private const int HilightAdj = 500;
  14. private const int WatermarkAdj = -50;
  15. private const int Range = 240;
  16. private const int HLSMax = Range;
  17. private const int RGBMax = 255;
  18. private const int Undefined = HLSMax * 2 / 3;
  19. private int hue;
  20. private int saturation;
  21. private int luminosity;
  22. private bool isSystemColors_Control;
  23. /// <summary>
  24. /// 构造函数
  25. /// </summary>
  26. /// <param name="color">RGBA颜色</param>
  27. public HLSColor(Color color)
  28. {
  29. isSystemColors_Control = (color.ToKnownColor() == SystemColors.Control.ToKnownColor());
  30. int r = color.R;
  31. int g = color.G;
  32. int b = color.B;
  33. int max, min; /* max and min RGB values */
  34. int sum, dif;
  35. int Rdelta, Gdelta, Bdelta; /* intermediate value: % of spread from max */
  36. /* calculate lightness */
  37. max = Math.Max(Math.Max(r, g), b);
  38. min = Math.Min(Math.Min(r, g), b);
  39. sum = max + min;
  40. luminosity = (((sum * HLSMax) + RGBMax) / (2 * RGBMax));
  41. dif = max - min;
  42. if (dif == 0)
  43. { /* r=g=b --> achromatic case */
  44. saturation = 0; /* saturation */
  45. hue = Undefined; /* hue */
  46. }
  47. else
  48. { /* chromatic case */
  49. /* saturation */
  50. if (luminosity <= (HLSMax / 2))
  51. saturation = (int)(((dif * (int)HLSMax) + (sum / 2)) / sum);
  52. else
  53. saturation = (int)((int)((dif * (int)HLSMax) + (int)((2 * RGBMax - sum) / 2))
  54. / (2 * RGBMax - sum));
  55. /* hue */
  56. Rdelta = (int)((((max - r) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
  57. Gdelta = (int)((((max - g) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
  58. Bdelta = (int)((((max - b) * (int)(HLSMax / 6)) + (dif / 2)) / dif);
  59. if ((int)r == max)
  60. hue = Bdelta - Gdelta;
  61. else if ((int)g == max)
  62. hue = (HLSMax / 3) + Rdelta - Bdelta;
  63. else /* B == cMax */
  64. hue = ((2 * HLSMax) / 3) + Gdelta - Rdelta;
  65. if (hue < 0)
  66. hue += HLSMax;
  67. if (hue > HLSMax)
  68. hue -= HLSMax;
  69. }
  70. }
  71. /// <summary>
  72. /// 色调
  73. /// </summary>
  74. public int Hue
  75. {
  76. get
  77. {
  78. return hue;
  79. }
  80. }
  81. /// <summary>
  82. /// 亮度
  83. /// </summary>
  84. public int Luminosity
  85. {
  86. get
  87. {
  88. return luminosity;
  89. }
  90. }
  91. /// <summary>
  92. /// 饱和度
  93. /// </summary>
  94. public int Saturation
  95. {
  96. get
  97. {
  98. return saturation;
  99. }
  100. }
  101. /// <summary>
  102. /// 获取减小指定亮度后的颜色
  103. /// </summary>
  104. /// <param name="percDarker">要减小的亮度</param>
  105. /// <returns>新的颜色</returns>
  106. public Color Darker(float percDarker)
  107. {
  108. if (isSystemColors_Control)
  109. {
  110. // With the usual color scheme, ControlDark/DarkDark is not exactly
  111. // what we would otherwise calculate
  112. if (percDarker == 0.0f)
  113. {
  114. return SystemColors.ControlDark;
  115. }
  116. else if (percDarker == 1.0f)
  117. {
  118. return SystemColors.ControlDarkDark;
  119. }
  120. else
  121. {
  122. Color dark = SystemColors.ControlDark;
  123. Color darkDark = SystemColors.ControlDarkDark;
  124. int dr = dark.R - darkDark.R;
  125. int dg = dark.G - darkDark.G;
  126. int db = dark.B - darkDark.B;
  127. return Color.FromArgb((byte)(dark.R - (byte)(dr * percDarker)),
  128. (byte)(dark.G - (byte)(dg * percDarker)),
  129. (byte)(dark.B - (byte)(db * percDarker)));
  130. }
  131. }
  132. else
  133. {
  134. int oneLum = 0;
  135. int zeroLum = NewLuma(ShadowAdj, true);
  136. return ColorFromHLS(hue, zeroLum - (int)((zeroLum - oneLum) * percDarker), saturation);
  137. }
  138. }
  139. /// <summary>
  140. /// 是否相等
  141. /// </summary>
  142. /// <param name="o">要比较的对象</param>
  143. /// <returns>相等返回true,否则返回false</returns>
  144. public override bool Equals(object o)
  145. {
  146. if (!(o is HLSColor))
  147. {
  148. return false;
  149. }
  150. HLSColor c = (HLSColor)o;
  151. return hue == c.hue &&
  152. saturation == c.saturation &&
  153. luminosity == c.luminosity &&
  154. isSystemColors_Control == c.isSystemColors_Control;
  155. }
  156. /// <summary>
  157. /// 是否相等
  158. /// </summary>
  159. /// <param name="a">颜色a</param>
  160. /// <param name="b">颜色b</param>
  161. /// <returns>相等返回true,否则返回false</returns>
  162. public static bool operator ==(HLSColor a, HLSColor b)
  163. {
  164. return a.Equals(b);
  165. }
  166. /// <summary>
  167. /// 是否不等
  168. /// </summary>
  169. /// <param name="a">颜色a</param>
  170. /// <param name="b">颜色b</param>
  171. /// <returns>不等返回true,否则返回false</returns>
  172. public static bool operator !=(HLSColor a, HLSColor b)
  173. {
  174. return !a.Equals(b);
  175. }
  176. /// <summary>
  177. /// 获取哈希码
  178. /// </summary>
  179. /// <returns>哈希码</returns>
  180. public override int GetHashCode()
  181. {
  182. return hue << 6 | saturation << 2 | luminosity;
  183. }
  184. /// <summary>
  185. /// 获取增加指定亮度后的颜色
  186. /// </summary>
  187. /// <param name="percLighter">要增加的亮度</param>
  188. /// <returns>新的颜色</returns>
  189. public Color Lighter(float percLighter)
  190. {
  191. if (isSystemColors_Control)
  192. {
  193. // With the usual color scheme, ControlLight/LightLight is not exactly
  194. // what we would otherwise calculate
  195. if (percLighter == 0.0f)
  196. {
  197. return SystemColors.ControlLight;
  198. }
  199. else if (percLighter == 1.0f)
  200. {
  201. return SystemColors.ControlLightLight;
  202. }
  203. else
  204. {
  205. Color light = SystemColors.ControlLight;
  206. Color lightLight = SystemColors.ControlLightLight;
  207. int dr = light.R - lightLight.R;
  208. int dg = light.G - lightLight.G;
  209. int db = light.B - lightLight.B;
  210. return Color.FromArgb((byte)(light.R - (byte)(dr * percLighter)),
  211. (byte)(light.G - (byte)(dg * percLighter)),
  212. (byte)(light.B - (byte)(db * percLighter)));
  213. }
  214. }
  215. else
  216. {
  217. int zeroLum = luminosity;
  218. int oneLum = NewLuma(HilightAdj, true);
  219. return ColorFromHLS(hue, zeroLum + (int)((oneLum - zeroLum) * percLighter), saturation);
  220. }
  221. }
  222. private int NewLuma(int n, bool scale)
  223. {
  224. return NewLuma(luminosity, n, scale);
  225. }
  226. private int NewLuma(int luminosity, int n, bool scale)
  227. {
  228. if (n == 0)
  229. return luminosity;
  230. if (scale)
  231. {
  232. if (n > 0)
  233. {
  234. return (int)(((int)luminosity * (1000 - n) + (Range + 1L) * n) / 1000);
  235. }
  236. else
  237. {
  238. return (int)(((int)luminosity * (n + 1000)) / 1000);
  239. }
  240. }
  241. int newLum = luminosity;
  242. newLum += (int)((long)n * Range / 1000);
  243. if (newLum < 0)
  244. newLum = 0;
  245. if (newLum > HLSMax)
  246. newLum = HLSMax;
  247. return newLum;
  248. }
  249. private Color ColorFromHLS(int hue, int luminosity, int saturation)
  250. {
  251. byte r, g, b; /* RGB component values */
  252. int magic1, magic2; /* calculated magic numbers (really!) */
  253. if (saturation == 0)
  254. { /* achromatic case */
  255. r = g = b = (byte)((luminosity * RGBMax) / HLSMax);
  256. if (hue != Undefined)
  257. {
  258. /* ERROR */
  259. }
  260. }
  261. else
  262. { /* chromatic case */
  263. /* set up magic numbers */
  264. if (luminosity <= (HLSMax / 2))
  265. magic2 = (int)((luminosity * ((int)HLSMax + saturation) + (HLSMax / 2)) / HLSMax);
  266. else
  267. magic2 = luminosity + saturation - (int)(((luminosity * saturation) + (int)(HLSMax / 2)) / HLSMax);
  268. magic1 = 2 * luminosity - magic2;
  269. /* get RGB, change units from HLSMax to RGBMax */
  270. r = (byte)(((HueToRGB(magic1, magic2, (int)(hue + (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
  271. g = (byte)(((HueToRGB(magic1, magic2, hue) * (int)RGBMax + (HLSMax / 2))) / HLSMax);
  272. b = (byte)(((HueToRGB(magic1, magic2, (int)(hue - (int)(HLSMax / 3))) * (int)RGBMax + (HLSMax / 2))) / (int)HLSMax);
  273. }
  274. return Color.FromArgb(r, g, b);
  275. }
  276. private int HueToRGB(int n1, int n2, int hue)
  277. {
  278. /* range check: note values passed add/subtract thirds of range */
  279. /* The following is redundant for WORD (unsigned int) */
  280. if (hue < 0)
  281. hue += HLSMax;
  282. if (hue > HLSMax)
  283. hue -= HLSMax;
  284. /* return r,g, or b value from this tridrant */
  285. if (hue < (HLSMax / 6))
  286. return (n1 + (((n2 - n1) * hue + (HLSMax / 12)) / (HLSMax / 6)));
  287. if (hue < (HLSMax / 2))
  288. return (n2);
  289. if (hue < ((HLSMax * 2) / 3))
  290. return (n1 + (((n2 - n1) * (((HLSMax * 2) / 3) - hue) + (HLSMax / 12)) / (HLSMax / 6)));
  291. else
  292. return (n1);
  293. }
  294. }
  295. }
  296. }