Question

I have a color of class Microsoft.Xna.Framework.Color. How can I change its hue (or get a new color with slightly different hue). Should I convert it to System.Drawing.Color, then somehow change it and convert back? I can't find any useful information on this anywhere.

EDIT Example: I have red color R:255, G:0, B:0. Now I want to get slightly more orange color. Then if I get this color and transform it again I'll get even more orange color, then after some transformations I'll go to yellow, green etc. I don't know exact values of ARGB of each color and I don't need them. I just need to change hue of a color by some factor (for example 10 degrees).

Was it helpful?

Solution

according to this documentation, you can pass whatever RGB(A) values you want into the XNA color class constructor. You can also use the R, B, and G properties to change them afterwards

example:

Color myColor = new Color(150, 100, 100);

myColor.R = 200

that example will change a red to a slightly deeper red.

An example of making a color go from Red to orange to yellow to green would be

Color myColor = new Color(255, 0, 0);

for(int i=0; i<255; i++)
{
    myColor.R--;
    myColor.G++
}

Red and Green make yellow, so higher numbers of red will make it redder, higher numbers of green will make it greener. same of both numbers make it redder.

You can change color incrementally in other ways too, so long as you know how the primary colors of light work.
You're never ever going to find a function called Color.MakeRedder() or Color.MakeGreener() It will always focus on some sort of mathmatical representation of the color, (RBG is most common but there are other representations)

If you want to convert Hue to RBG Here is a guide on how to do it

What would probably be easiest is to keep track of a System.Drawing.Color class as your base color class, and modify your XNA Color Class based on your System.Drawing.Color class accordingly.

If you want to get really adventurous, you can see if it is possible to make a class that extends(inherits from) Microsoft.Xna.Framework.Color, override the R, G, and B properties, so that they are based off of an underlying System.Drawing.Color object

OTHER TIPS

You should use the A R G B properties and change the values to get different nyansers.

For example:

Color color = new Color(0,0,0);
//Then you can change the argb properties:
color.A = 10;
color.R = 15;
color.G = 9;
color.B = 25;

If I understand you need something like this:

public static class Utilities
{
    public static void Increase(this Color color, int value)
    {
        if(color.R >= color.G && color.R >= color.B)
           color.R += value;
        else if(color.G >= color.R && color.G >= color.B)
           color.G += value;
        else
           color.B += value;
    }

    public static void Decrease(this Color color, int value)
    {
        if(color.R <= color.G && color.R <= color.B)
           color.R -= value;
        else if(color.G <= color.R && color.G <= color.B)
           color.G -= value;
        else
           color.B -= value;
    }
}

Then:

Color myColor = new Color(10,0,0);
myColor.Increase(10);
//or
myColor.Decrease(10);

I did some research and found this post which has C++ code:

http://www.cs.rit.edu/~ncs/color/t_convert.html

I've modified the code to be C#, to have an IncreaseHueBy method, and to fix a few bugs:

 public static void IncreaseHueBy(ref Color color, float value, out float hue)
 {
     float h, s, v;

     RgbToHsv(color.R, color.G, color.B, out h, out s, out v);
     h += value;

     float r, g, b;

     HsvToRgb(h, s, v, out r, out g, out b);


     color.R = (byte)(r);
     color.G = (byte)(g);
     color.B = (byte)(b);

     hue = h;
 }

 static void  RgbToHsv(float r, float g, float b, out float h, out float s, out float v)
 {
     float min, max, delta;
     min = System.Math.Min(System.Math.Min(r, g), b);
     max = System.Math.Max(System.Math.Max(r, g), b);
     v = max;               // v
     delta = max - min;
     if (max != 0)
     {
         s = delta / max;       // s

         if (r == max)
             h = (g - b) / delta;       // between yellow & magenta
         else if (g == max)
             h = 2 + (b - r) / delta;   // between cyan & yellow
         else
             h = 4 + (r - g) / delta;   // between magenta & cyan
         h *= 60;               // degrees
         if (h < 0)
             h += 360;
     }
     else
     {
         // r = g = b = 0       // s = 0, v is undefined
         s = 0;
         h = -1;
     }

 }
 static void HsvToRgb(float h, float s, float v, out float r, out float g, out float b)
 {
     // Keeps h from going over 360
     h = h - ((int)(h / 360) * 360);

     int i;
     float f, p, q, t;
     if (s == 0)
     {
         // achromatic (grey)
         r = g = b = v;
         return;
     }
     h /= 60;           // sector 0 to 5

     i = (int)h;
     f = h - i;         // factorial part of h
     p = v * (1 - s);
     q = v * (1 - s * f);
     t = v * (1 - s * (1 - f));
     switch (i)
     {
         case 0:
             r = v;
             g = t;
             b = p;
             break;
         case 1:
             r = q;
             g = v;
             b = p;
             break;
         case 2:
             r = p;
             g = v;
             b = t;
             break;
         case 3:
             r = p;
             g = q;
             b = v;
             break;
         case 4:
             r = t;
             g = p;
             b = v;
             break;
         default:       // case 5:
             r = v;
             g = p;
             b = q;
             break;
     }
 }

I tested it by using a value of 1 to increase the hue by 1 every frame and it worked fairly well. Notice there may be some rounding errors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top