SORTPAL.CPP 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /****************************************************************************
  19. *
  20. * C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
  21. *
  22. *----------------------------------------------------------------------------
  23. *
  24. * FILE
  25. * sortpal.c
  26. *
  27. * DESCRIPTION
  28. * Palette sorting routines. (32-Bit protected mode)
  29. *
  30. * PROGRAMMER
  31. * Denzil E. Long, Jr.
  32. * Bill Randolph
  33. *
  34. * DATE
  35. * January 26, 1995
  36. *
  37. *----------------------------------------------------------------------------
  38. *
  39. * PUBLIC
  40. * SortPalette - Sort a palette.
  41. * Comp_Luminance - Compare the luminace of two 24-bit palette entries.
  42. * Comp_HSV - Compare the HSV of two 24-bit palette entries.
  43. * RGB_To_HSV - Convert RGB color to HSV color.
  44. *
  45. ****************************************************************************/
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include "palette.h"
  49. /*---------------------------------------------------------------------------
  50. * PRIVATE DECLARATIONS
  51. *-------------------------------------------------------------------------*/
  52. /* HSV color model */
  53. #define DIVIDE_WITH_ROUND(n,d) (unsigned short)(((n)/(d))+ \
  54. (unsigned short)(((n)%(d)) >= (((d)+1)>>1)))
  55. #define HSV_BASE 255
  56. #define HUE_WEIGHT 10L
  57. #define SATURATION_WEIGHT 100L
  58. #define VALUE_WEIGHT 1000L
  59. /* Prototypes */
  60. static int Comp_Luminance(const void *elem1, const void *elem2);
  61. static int Comp_HSV(const void *elem1, const void *elem2);
  62. static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
  63. unsigned short *h, unsigned short *s, unsigned short *v);
  64. /****************************************************************************
  65. *
  66. * NAME
  67. * SortPalette - Sort a palette.
  68. *
  69. * SYNOPSIS
  70. * SortPalette(Palette, NumColors)
  71. *
  72. * void SortPalette(unsigned char *, long);
  73. *
  74. * FUNCTION
  75. * Sort the palette colors.
  76. *
  77. * INPUTS
  78. * Palette - Pointer to palette to sort.
  79. * NumColors - Number of colors in the palette.
  80. *
  81. * RESULT
  82. * NONE
  83. *
  84. ****************************************************************************/
  85. void SortPalette(unsigned char *pal, long numcolors)
  86. {
  87. qsort(pal, numcolors, 3, Comp_Luminance);
  88. pal[0] = 0;
  89. pal[1] = 0;
  90. pal[2] = 0;
  91. }
  92. /****************************************************************************
  93. *
  94. * NAME
  95. * Comp_Luminance - Compare the luminace of two 24-bit palette entries.
  96. *
  97. * SYNOPSIS
  98. * Result = Comp_Luminance(Color1, Color2)
  99. *
  100. * long Comp_Luminance(void *, void *);
  101. *
  102. * FUNCTION
  103. * Compare the luminace of the two colors and determine which color is
  104. * brighter than the other.
  105. *
  106. * The computation used is:
  107. * Luminance = (red * .299) + (green * .587) + (blue * .114)
  108. *
  109. * INPUTS
  110. * Color1 - Pointer to palette entry.
  111. * Color2 - Pointer to palette entry.
  112. *
  113. * RESULT
  114. * Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
  115. *
  116. ****************************************************************************/
  117. static int Comp_Luminance(const void *elem1, const void *elem2)
  118. {
  119. unsigned char *pal;
  120. long r,g,b;
  121. long total1,total2;
  122. /* Compute luminance for color1 */
  123. pal = (unsigned char *)elem1;
  124. r = ((long)pal[0]);
  125. g = ((long)pal[1]);
  126. b = ((long)pal[2]);
  127. total1 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
  128. /* Compute luminance for color2 */
  129. pal = (unsigned char *)elem2;
  130. r = ((long)pal[0]);
  131. g = ((long)pal[1]);
  132. b = ((long)pal[2]);
  133. total2 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
  134. if (total1 < total2) {
  135. return (-1);
  136. } else if (total1 > total2) {
  137. return (1);
  138. } else {
  139. return (0);
  140. }
  141. }
  142. /****************************************************************************
  143. *
  144. * NAME
  145. * Comp_HSV - Compare the HSV of two 24-bit palette entries.
  146. *
  147. * SYNOPSIS
  148. * Result = Comp_HSV(Color1, Color2)
  149. *
  150. * long Comp_HSV(void *, void *);
  151. *
  152. * FUNCTION
  153. * Compare the HSV color values of two colors and determine the
  154. * relationship between the colors in the color space.
  155. *
  156. * INPUTS
  157. * Color1 - Pointer to 1st palette entry.
  158. * Color2 - Pointer to 2nd palette entry.
  159. *
  160. * RESULT
  161. * Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
  162. *
  163. ****************************************************************************/
  164. static int Comp_HSV(const void *elem1, const void *elem2)
  165. {
  166. unsigned char *pal;
  167. unsigned char r,g,b;
  168. unsigned short h,s,v;
  169. unsigned long key1,key2;
  170. long retval;
  171. /* Convert 1st element to HSV */
  172. pal = (unsigned char *)elem1;
  173. r = pal[0];
  174. g = pal[1];
  175. b = pal[2];
  176. RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
  177. key1 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
  178. /* Convert 2nd element to HSV */
  179. pal = (unsigned char *)elem2;
  180. r = pal[0];
  181. g = pal[1];
  182. b = pal[2];
  183. RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
  184. key2 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
  185. if (key1 != key2) {
  186. retval = ((key1 < key2) ? -1 : 1);
  187. } else {
  188. retval = 0;
  189. }
  190. return (retval);
  191. }
  192. /***************************************************************************
  193. *
  194. * NAME
  195. * RGB_To_HSV - Convert RGB color to HSV color.
  196. *
  197. * SYNOPSIS
  198. * RGB_To_HSV(R, G, B, H, S, V)
  199. *
  200. * void RGB_To_HSV(unsigned short, unsigned short, unsigned short,
  201. * unsigned short *, unsigned short *, unsigned short *);
  202. *
  203. * FUNCTION
  204. * Convert the RBG color to a HSV color. Assumes 8 bits per gun of R, G
  205. * and B data. Also the HSV is based on a 255 degree scale rather than
  206. * the more accurate 360 degree scale.
  207. *
  208. * INPUTS
  209. * R - Red gun value.
  210. * G - Green gun value.
  211. * B - Blue gun value.
  212. * H - Pointer to H value. (H will be set upon return of this function)
  213. * S - Pointer to S value. (S will be set upon return of this function)
  214. * V - Pointer to V value. (V will be set upon return of this function)
  215. *
  216. * RESULT
  217. * NONE
  218. *
  219. ***************************************************************************/
  220. static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
  221. unsigned short *h, unsigned short *s, unsigned short *v)
  222. {
  223. unsigned short m;
  224. unsigned short r1;
  225. unsigned short g1;
  226. unsigned short b1;
  227. unsigned short tmp;
  228. /* Set hue to default. */
  229. *h = 0;
  230. /* Set v = Max(r,g,b) to find dominant primary color. */
  231. *v = ((r > g) ? r : g);
  232. if (b > *v) {
  233. *v = b;
  234. }
  235. /* Set m = min(r,g,b) to find amount of white. */
  236. m = ((r < g) ? r : g);
  237. if (b < m) {
  238. m = b;
  239. }
  240. /* Determine the normalized saturation. */
  241. if (*v != 0) {
  242. *s = DIVIDE_WITH_ROUND((*v - m) * HSV_BASE, *v);
  243. } else {
  244. *s = 0;
  245. }
  246. if (*s != 0) {
  247. tmp = *v - m;
  248. r1 = DIVIDE_WITH_ROUND((*v - r) * HSV_BASE, tmp);
  249. g1 = DIVIDE_WITH_ROUND((*v - g) * HSV_BASE, tmp);
  250. b1 = DIVIDE_WITH_ROUND((*v - b) * HSV_BASE, tmp);
  251. /* Find effect of second most predominant color.
  252. * In which section of the hexagon of colors does the color lie?
  253. */
  254. if ((*v) == r) {
  255. if (m == g) {
  256. *h = 5 * HSV_BASE + b1;
  257. } else {
  258. *h = 1 * HSV_BASE - g1;
  259. }
  260. } else {
  261. if ((*v) == g) {
  262. if (m == b) {
  263. *h = 1 * HSV_BASE + r1;
  264. } else {
  265. *h = 3 * HSV_BASE - b1;
  266. }
  267. } else {
  268. if (m == r) {
  269. *h = 3 * HSV_BASE + g1;
  270. } else {
  271. *h = 5 * HSV_BASE - r1;
  272. }
  273. }
  274. }
  275. /* Divide by six and round. */
  276. *h = DIVIDE_WITH_ROUND(*h, 6);
  277. }
  278. }