CmColor.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmColor.h"
  25. #include "CmMath.h"
  26. namespace CamelotEngine {
  27. const Color Color::ZERO = Color(0.0,0.0,0.0,0.0);
  28. const Color Color::Black = Color(0.0,0.0,0.0);
  29. const Color Color::White = Color(1.0,1.0,1.0);
  30. const Color Color::Red = Color(1.0,0.0,0.0);
  31. const Color Color::Green = Color(0.0,1.0,0.0);
  32. const Color Color::Blue = Color(0.0,0.0,1.0);
  33. //---------------------------------------------------------------------
  34. #if CM_ENDIAN == CM_ENDIAN_BIG
  35. ABGR Color::getAsABGR(void) const
  36. #else
  37. RGBA Color::getAsRGBA(void) const
  38. #endif
  39. {
  40. UINT8 val8;
  41. UINT32 val32 = 0;
  42. // Convert to 32bit pattern
  43. // (RGBA = 8888)
  44. // Red
  45. val8 = static_cast<UINT8>(r * 255);
  46. val32 = val8 << 24;
  47. // Green
  48. val8 = static_cast<UINT8>(g * 255);
  49. val32 += val8 << 16;
  50. // Blue
  51. val8 = static_cast<UINT8>(b * 255);
  52. val32 += val8 << 8;
  53. // Alpha
  54. val8 = static_cast<UINT8>(a * 255);
  55. val32 += val8;
  56. return val32;
  57. }
  58. //---------------------------------------------------------------------
  59. #if CM_ENDIAN == CM_ENDIAN_BIG
  60. BGRA Color::getAsBGRA(void) const
  61. #else
  62. ARGB Color::getAsARGB(void) const
  63. #endif
  64. {
  65. UINT8 val8;
  66. UINT32 val32 = 0;
  67. // Convert to 32bit pattern
  68. // (ARGB = 8888)
  69. // Alpha
  70. val8 = static_cast<UINT8>(a * 255);
  71. val32 = val8 << 24;
  72. // Red
  73. val8 = static_cast<UINT8>(r * 255);
  74. val32 += val8 << 16;
  75. // Green
  76. val8 = static_cast<UINT8>(g * 255);
  77. val32 += val8 << 8;
  78. // Blue
  79. val8 = static_cast<UINT8>(b * 255);
  80. val32 += val8;
  81. return val32;
  82. }
  83. //---------------------------------------------------------------------
  84. #if CM_ENDIAN == CM_ENDIAN_BIG
  85. ARGB Color::getAsARGB(void) const
  86. #else
  87. BGRA Color::getAsBGRA(void) const
  88. #endif
  89. {
  90. UINT8 val8;
  91. UINT32 val32 = 0;
  92. // Convert to 32bit pattern
  93. // (ARGB = 8888)
  94. // Blue
  95. val8 = static_cast<UINT8>(b * 255);
  96. val32 = val8 << 24;
  97. // Green
  98. val8 = static_cast<UINT8>(g * 255);
  99. val32 += val8 << 16;
  100. // Red
  101. val8 = static_cast<UINT8>(r * 255);
  102. val32 += val8 << 8;
  103. // Alpha
  104. val8 = static_cast<UINT8>(a * 255);
  105. val32 += val8;
  106. return val32;
  107. }
  108. //---------------------------------------------------------------------
  109. #if CM_ENDIAN == CM_ENDIAN_BIG
  110. RGBA Color::getAsRGBA(void) const
  111. #else
  112. ABGR Color::getAsABGR(void) const
  113. #endif
  114. {
  115. UINT8 val8;
  116. UINT32 val32 = 0;
  117. // Convert to 32bit pattern
  118. // (ABRG = 8888)
  119. // Alpha
  120. val8 = static_cast<UINT8>(a * 255);
  121. val32 = val8 << 24;
  122. // Blue
  123. val8 = static_cast<UINT8>(b * 255);
  124. val32 += val8 << 16;
  125. // Green
  126. val8 = static_cast<UINT8>(g * 255);
  127. val32 += val8 << 8;
  128. // Red
  129. val8 = static_cast<UINT8>(r * 255);
  130. val32 += val8;
  131. return val32;
  132. }
  133. //---------------------------------------------------------------------
  134. #if CM_ENDIAN == CM_ENDIAN_BIG
  135. void Color::setAsABGR(const ABGR val)
  136. #else
  137. void Color::setAsRGBA(const RGBA val)
  138. #endif
  139. {
  140. UINT32 val32 = val;
  141. // Convert from 32bit pattern
  142. // (RGBA = 8888)
  143. // Red
  144. r = ((val32 >> 24) & 0xFF) / 255.0f;
  145. // Green
  146. g = ((val32 >> 16) & 0xFF) / 255.0f;
  147. // Blue
  148. b = ((val32 >> 8) & 0xFF) / 255.0f;
  149. // Alpha
  150. a = (val32 & 0xFF) / 255.0f;
  151. }
  152. //---------------------------------------------------------------------
  153. #if CM_ENDIAN == CM_ENDIAN_BIG
  154. void Color::setAsBGRA(const BGRA val)
  155. #else
  156. void Color::setAsARGB(const ARGB val)
  157. #endif
  158. {
  159. UINT32 val32 = val;
  160. // Convert from 32bit pattern
  161. // (ARGB = 8888)
  162. // Alpha
  163. a = ((val32 >> 24) & 0xFF) / 255.0f;
  164. // Red
  165. r = ((val32 >> 16) & 0xFF) / 255.0f;
  166. // Green
  167. g = ((val32 >> 8) & 0xFF) / 255.0f;
  168. // Blue
  169. b = (val32 & 0xFF) / 255.0f;
  170. }
  171. //---------------------------------------------------------------------
  172. #if CM_ENDIAN == CM_ENDIAN_BIG
  173. void Color::setAsARGB(const ARGB val)
  174. #else
  175. void Color::setAsBGRA(const BGRA val)
  176. #endif
  177. {
  178. UINT32 val32 = val;
  179. // Convert from 32bit pattern
  180. // (ARGB = 8888)
  181. // Blue
  182. b = ((val32 >> 24) & 0xFF) / 255.0f;
  183. // Green
  184. g = ((val32 >> 16) & 0xFF) / 255.0f;
  185. // Red
  186. r = ((val32 >> 8) & 0xFF) / 255.0f;
  187. // Alpha
  188. a = (val32 & 0xFF) / 255.0f;
  189. }
  190. //---------------------------------------------------------------------
  191. #if CM_ENDIAN == CM_ENDIAN_BIG
  192. void Color::setAsRGBA(const RGBA val)
  193. #else
  194. void Color::setAsABGR(const ABGR val)
  195. #endif
  196. {
  197. UINT32 val32 = val;
  198. // Convert from 32bit pattern
  199. // (ABGR = 8888)
  200. // Alpha
  201. a = ((val32 >> 24) & 0xFF) / 255.0f;
  202. // Blue
  203. b = ((val32 >> 16) & 0xFF) / 255.0f;
  204. // Green
  205. g = ((val32 >> 8) & 0xFF) / 255.0f;
  206. // Red
  207. r = (val32 & 0xFF) / 255.0f;
  208. }
  209. //---------------------------------------------------------------------
  210. bool Color::operator==(const Color& rhs) const
  211. {
  212. return (r == rhs.r &&
  213. g == rhs.g &&
  214. b == rhs.b &&
  215. a == rhs.a);
  216. }
  217. //---------------------------------------------------------------------
  218. bool Color::operator!=(const Color& rhs) const
  219. {
  220. return !(*this == rhs);
  221. }
  222. //---------------------------------------------------------------------
  223. void Color::setHSB(float hue, float saturation, float brightness)
  224. {
  225. // wrap hue
  226. if (hue > 1.0f)
  227. {
  228. hue -= (int)hue;
  229. }
  230. else if (hue < 0.0f)
  231. {
  232. hue += (int)hue + 1;
  233. }
  234. // clamp saturation / brightness
  235. saturation = std::min(saturation, (float)1.0);
  236. saturation = std::max(saturation, (float)0.0);
  237. brightness = std::min(brightness, (float)1.0);
  238. brightness = std::max(brightness, (float)0.0);
  239. if (brightness == 0.0f)
  240. {
  241. // early exit, this has to be black
  242. r = g = b = 0.0f;
  243. return;
  244. }
  245. if (saturation == 0.0f)
  246. {
  247. // early exit, this has to be grey
  248. r = g = b = brightness;
  249. return;
  250. }
  251. float hueDomain = hue * 6.0f;
  252. if (hueDomain >= 6.0f)
  253. {
  254. // wrap around, and allow mathematical errors
  255. hueDomain = 0.0f;
  256. }
  257. unsigned short domain = (unsigned short)hueDomain;
  258. float f1 = brightness * (1 - saturation);
  259. float f2 = brightness * (1 - saturation * (hueDomain - domain));
  260. float f3 = brightness * (1 - saturation * (1 - (hueDomain - domain)));
  261. switch (domain)
  262. {
  263. case 0:
  264. // red domain; green ascends
  265. r = brightness;
  266. g = f3;
  267. b = f1;
  268. break;
  269. case 1:
  270. // yellow domain; red descends
  271. r = f2;
  272. g = brightness;
  273. b = f1;
  274. break;
  275. case 2:
  276. // green domain; blue ascends
  277. r = f1;
  278. g = brightness;
  279. b = f3;
  280. break;
  281. case 3:
  282. // cyan domain; green descends
  283. r = f1;
  284. g = f2;
  285. b = brightness;
  286. break;
  287. case 4:
  288. // blue domain; red ascends
  289. r = f3;
  290. g = f1;
  291. b = brightness;
  292. break;
  293. case 5:
  294. // magenta domain; blue descends
  295. r = brightness;
  296. g = f1;
  297. b = f2;
  298. break;
  299. }
  300. }
  301. //---------------------------------------------------------------------
  302. void Color::getHSB(float* hue, float* saturation, float* brightness) const
  303. {
  304. float vMin = std::min(r, std::min(g, b));
  305. float vMax = std::max(r, std::max(g, b));
  306. float delta = vMax - vMin;
  307. *brightness = vMax;
  308. if (Math::RealEqual(delta, 0.0f, 1e-6f))
  309. {
  310. // grey
  311. *hue = 0;
  312. *saturation = 0;
  313. }
  314. else
  315. {
  316. // a colour
  317. *saturation = delta / vMax;
  318. float deltaR = (((vMax - r) / 6.0f) + (delta / 2.0f)) / delta;
  319. float deltaG = (((vMax - g) / 6.0f) + (delta / 2.0f)) / delta;
  320. float deltaB = (((vMax - b) / 6.0f) + (delta / 2.0f)) / delta;
  321. if (Math::RealEqual(r, vMax))
  322. *hue = deltaB - deltaG;
  323. else if (Math::RealEqual(g, vMax))
  324. *hue = 0.3333333f + deltaR - deltaB;
  325. else if (Math::RealEqual(b, vMax))
  326. *hue = 0.6666667f + deltaG - deltaR;
  327. if (*hue < 0.0f)
  328. *hue += 1.0f;
  329. if (*hue > 1.0f)
  330. *hue -= 1.0f;
  331. }
  332. }
  333. }