public static string RgbToHex(Rgb rgb) { byte rByte = (byte)Math.Round(rgb.R * 255.0); byte gByte = (byte)Math.Round(rgb.G * 255.0); byte bByte = (byte)Math.Round(rgb.B * 255.0); UInt64 hexValue = ((UInt64)rByte << 16) + ((UInt64)gByte << 8) + (UInt64)bByte; // Uno Doc: Using C#/.net string methods instead string hexString = string.Format(CultureInfo.InvariantCulture, "#{0:X6}", hexValue); // We'll size this string to accommodate "#XXXXXX" - i.e., a full RGB number with a # sign. //wchar_t hexString[8]; //winrt::check_hresult(StringCchPrintfW(&hexString[0], 8, L"#%06X", hexValue)); return(hexString); }
public static Hsv RgbToHsv(Rgb rgb) { double hue; double saturation; double value; double max = rgb.R >= rgb.G ? (rgb.R >= rgb.B ? rgb.R : rgb.B) : (rgb.G >= rgb.B ? rgb.G : rgb.B); double min = rgb.R <= rgb.G ? (rgb.R <= rgb.B ? rgb.R : rgb.B) : (rgb.G <= rgb.B ? rgb.G : rgb.B); // The value, a number between 0 and 1, is the largest of R, G, and B (divided by 255). // Conceptually speaking, it represents how much color is present. // If at least one of R, G, B is 255, then there exists as much color as there can be. // If RGB = (0, 0, 0), then there exists no color at all - a value of zero corresponds // to black (i.e., the absence of any color). value = max; // The "chroma" of the color is a value directly proportional to the extent to which // the color diverges from greyscale. If, for example, we have RGB = (255, 255, 0), // then the chroma is maximized - this is a pure yellow, no grey of any kind. // On the other hand, if we have RGB = (128, 128, 128), then the chroma being zero // implies that this color is pure greyscale, with no actual hue to be found. double chroma = max - min; // If the chrome is zero, then hue is technically undefined - a greyscale color // has no hue. For the sake of convenience, we'll just set hue to zero, since // it will be unused in this circumstance. Since the color is purely grey, // saturation is also equal to zero - you can think of saturation as basically // a measure of hue intensity, such that no hue at all corresponds to a // nonexistent intensity. if (chroma == 0) { hue = 0.0; saturation = 0.0; } else { // In this block, hue is properly defined, so we'll extract both hue // and saturation information from the RGB color. // Hue can be thought of as a cyclical thing, between 0 degrees and 360 degrees. // A hue of 0 degrees is red; 120 degrees is green; 240 degrees is blue; and 360 is back to red. // Every other hue is somewhere between either red and green, green and blue, and blue and red, // so every other hue can be thought of as an angle on this color wheel. // These if/else statements determines where on this color wheel our color lies. if (rgb.R == max) { // If the red channel is the most pronounced channel, then we exist // somewhere between (-60, 60) on the color wheel - i.e., the section around 0 degrees // where red dominates. We figure out where in that section we are exactly // by considering whether the green or the blue channel is greater - by subtracting green from blue, // then if green is greater, we'll nudge ourselves closer to 60, whereas if blue is greater, then // we'll nudge ourselves closer to -60. We then divide by chroma (which will actually make the result larger, // since chroma is a value between 0 and 1) to normalize the value to ensure that we get the right hue // even if we're very close to greyscale. hue = 60 * (rgb.G - rgb.B) / chroma; } else if (rgb.G == max) { // We do the exact same for the case where the green channel is the most pronounced channel, // only this time we want to see if we should tilt towards the blue direction or the red direction. // We add 120 to center our value in the green third of the color wheel. hue = 120 + 60 * (rgb.B - rgb.R) / chroma; } else // rgb.B == max { // And we also do the exact same for the case where the blue channel is the most pronounced channel, // only this time we want to see if we should tilt towards the red direction or the green direction. // We add 240 to center our value in the blue third of the color wheel. hue = 240 + 60 * (rgb.R - rgb.G) / chroma; } // Since we want to work within the range [0, 360), we'll add 360 to any value less than zero - // this will bump red values from within -60 to -1 to 300 to 359. The hue is the same at both values. if (hue < 0.0) { hue += 360.0; } // The saturation, our final HSV axis, can be thought of as a value between 0 and 1 indicating how intense our color is. // To find it, we divide the chroma - the distance between the minimum and the maximum RGB channels - by the maximum channel (i.e., the value). // This effectively normalizes the chroma - if the maximum is 0.5 and the minimum is 0, the saturation will be (0.5 - 0) / 0.5 = 1, // meaning that although this color is not as bright as it can be, the dark color is as intense as it possibly could be. // If, on the other hand, the maximum is 0.5 and the minimum is 0.25, then the saturation will be (0.5 - 0.25) / 0.5 = 0.5, // meaning that this color is partially washed out. // A saturation value of 0 corresponds to a greyscale color, one in which the color is *completely* washed out and there is no actual hue. saturation = chroma / value; } return(new Hsv(hue, saturation, value)); }