| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /****************************************************************************
- *
- * 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
- *
- *----------------------------------------------------------------------------
- *
- * FILE
- * sortpal.c
- *
- * DESCRIPTION
- * Palette sorting routines. (32-Bit protected mode)
- *
- * PROGRAMMER
- * Denzil E. Long, Jr.
- * Bill Randolph
- *
- * DATE
- * January 26, 1995
- *
- *----------------------------------------------------------------------------
- *
- * PUBLIC
- * SortPalette - Sort a palette.
- * Comp_Luminance - Compare the luminace of two 24-bit palette entries.
- * Comp_HSV - Compare the HSV of two 24-bit palette entries.
- * RGB_To_HSV - Convert RGB color to HSV color.
- *
- ****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include "palette.h"
- /*---------------------------------------------------------------------------
- * PRIVATE DECLARATIONS
- *-------------------------------------------------------------------------*/
- /* HSV color model */
- #define DIVIDE_WITH_ROUND(n,d) (unsigned short)(((n)/(d))+ \
- (unsigned short)(((n)%(d)) >= (((d)+1)>>1)))
- #define HSV_BASE 255
- #define HUE_WEIGHT 10L
- #define SATURATION_WEIGHT 100L
- #define VALUE_WEIGHT 1000L
- /* Prototypes */
- static int Comp_Luminance(const void *elem1, const void *elem2);
- static int Comp_HSV(const void *elem1, const void *elem2);
- static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
- unsigned short *h, unsigned short *s, unsigned short *v);
- /****************************************************************************
- *
- * NAME
- * SortPalette - Sort a palette.
- *
- * SYNOPSIS
- * SortPalette(Palette, NumColors)
- *
- * void SortPalette(unsigned char *, long);
- *
- * FUNCTION
- * Sort the palette colors.
- *
- * INPUTS
- * Palette - Pointer to palette to sort.
- * NumColors - Number of colors in the palette.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void SortPalette(unsigned char *pal, long numcolors)
- {
- qsort(pal, numcolors, 3, Comp_Luminance);
- pal[0] = 0;
- pal[1] = 0;
- pal[2] = 0;
- }
- /****************************************************************************
- *
- * NAME
- * Comp_Luminance - Compare the luminace of two 24-bit palette entries.
- *
- * SYNOPSIS
- * Result = Comp_Luminance(Color1, Color2)
- *
- * long Comp_Luminance(void *, void *);
- *
- * FUNCTION
- * Compare the luminace of the two colors and determine which color is
- * brighter than the other.
- *
- * The computation used is:
- * Luminance = (red * .299) + (green * .587) + (blue * .114)
- *
- * INPUTS
- * Color1 - Pointer to palette entry.
- * Color2 - Pointer to palette entry.
- *
- * RESULT
- * Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
- *
- ****************************************************************************/
- static int Comp_Luminance(const void *elem1, const void *elem2)
- {
- unsigned char *pal;
- long r,g,b;
- long total1,total2;
- /* Compute luminance for color1 */
- pal = (unsigned char *)elem1;
- r = ((long)pal[0]);
- g = ((long)pal[1]);
- b = ((long)pal[2]);
- total1 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
- /* Compute luminance for color2 */
- pal = (unsigned char *)elem2;
- r = ((long)pal[0]);
- g = ((long)pal[1]);
- b = ((long)pal[2]);
- total2 = ((r * 19595L) + (g * 38470L) + (b * 7471L));
- if (total1 < total2) {
- return (-1);
- } else if (total1 > total2) {
- return (1);
- } else {
- return (0);
- }
- }
- /****************************************************************************
- *
- * NAME
- * Comp_HSV - Compare the HSV of two 24-bit palette entries.
- *
- * SYNOPSIS
- * Result = Comp_HSV(Color1, Color2)
- *
- * long Comp_HSV(void *, void *);
- *
- * FUNCTION
- * Compare the HSV color values of two colors and determine the
- * relationship between the colors in the color space.
- *
- * INPUTS
- * Color1 - Pointer to 1st palette entry.
- * Color2 - Pointer to 2nd palette entry.
- *
- * RESULT
- * Result - 0 = same, 1 = Color1 > Color2, -1 = Color1 < Color2
- *
- ****************************************************************************/
- static int Comp_HSV(const void *elem1, const void *elem2)
- {
- unsigned char *pal;
- unsigned char r,g,b;
- unsigned short h,s,v;
- unsigned long key1,key2;
- long retval;
- /* Convert 1st element to HSV */
- pal = (unsigned char *)elem1;
- r = pal[0];
- g = pal[1];
- b = pal[2];
- RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
- key1 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
- /* Convert 2nd element to HSV */
- pal = (unsigned char *)elem2;
- r = pal[0];
- g = pal[1];
- b = pal[2];
- RGB_To_HSV((unsigned short)r,(unsigned short)g,(unsigned short)b,&h,&s,&v);
- key2 = ((h * HUE_WEIGHT) + (s * SATURATION_WEIGHT) + (v * VALUE_WEIGHT));
- if (key1 != key2) {
- retval = ((key1 < key2) ? -1 : 1);
- } else {
- retval = 0;
- }
- return (retval);
- }
- /***************************************************************************
- *
- * NAME
- * RGB_To_HSV - Convert RGB color to HSV color.
- *
- * SYNOPSIS
- * RGB_To_HSV(R, G, B, H, S, V)
- *
- * void RGB_To_HSV(unsigned short, unsigned short, unsigned short,
- * unsigned short *, unsigned short *, unsigned short *);
- *
- * FUNCTION
- * Convert the RBG color to a HSV color. Assumes 8 bits per gun of R, G
- * and B data. Also the HSV is based on a 255 degree scale rather than
- * the more accurate 360 degree scale.
- *
- * INPUTS
- * R - Red gun value.
- * G - Green gun value.
- * B - Blue gun value.
- * H - Pointer to H value. (H will be set upon return of this function)
- * S - Pointer to S value. (S will be set upon return of this function)
- * V - Pointer to V value. (V will be set upon return of this function)
- *
- * RESULT
- * NONE
- *
- ***************************************************************************/
- static void RGB_To_HSV(unsigned short r, unsigned short g, unsigned short b,
- unsigned short *h, unsigned short *s, unsigned short *v)
- {
- unsigned short m;
- unsigned short r1;
- unsigned short g1;
- unsigned short b1;
- unsigned short tmp;
- /* Set hue to default. */
- *h = 0;
- /* Set v = Max(r,g,b) to find dominant primary color. */
- *v = ((r > g) ? r : g);
- if (b > *v) {
- *v = b;
- }
- /* Set m = min(r,g,b) to find amount of white. */
- m = ((r < g) ? r : g);
- if (b < m) {
- m = b;
- }
- /* Determine the normalized saturation. */
- if (*v != 0) {
- *s = DIVIDE_WITH_ROUND((*v - m) * HSV_BASE, *v);
- } else {
- *s = 0;
- }
- if (*s != 0) {
- tmp = *v - m;
- r1 = DIVIDE_WITH_ROUND((*v - r) * HSV_BASE, tmp);
- g1 = DIVIDE_WITH_ROUND((*v - g) * HSV_BASE, tmp);
- b1 = DIVIDE_WITH_ROUND((*v - b) * HSV_BASE, tmp);
- /* Find effect of second most predominant color.
- * In which section of the hexagon of colors does the color lie?
- */
- if ((*v) == r) {
- if (m == g) {
- *h = 5 * HSV_BASE + b1;
- } else {
- *h = 1 * HSV_BASE - g1;
- }
- } else {
- if ((*v) == g) {
- if (m == b) {
- *h = 1 * HSV_BASE + r1;
- } else {
- *h = 3 * HSV_BASE - b1;
- }
- } else {
- if (m == r) {
- *h = 3 * HSV_BASE + g1;
- } else {
- *h = 5 * HSV_BASE - r1;
- }
- }
- }
- /* Divide by six and round. */
- *h = DIVIDE_WITH_ROUND(*h, 6);
- }
- }
|