ごくまれに16進数カラーを扱わないとならないことがあるのですが、直感的に入力することが難しいのでHSVカラーで編集できるようなツールを作りたいなと思うことがあります。その準備で色を変換する関数を書いてみました。
以下はC#コンソールアプリのコードです。
class Program { static void Main(string[] args) { // R78, G244, B32のカラーを16進数カラーへ変換します int[] rgb = { 78, 244, 32 }; // 0~1へクランプ Vector3 color = rgbToClamp01(rgb); // 16進数カラーへ変換 string hexColor = clamp01ToHex(color); // 「4ef420」が返ります Console.WriteLine("HEX: #" + hexColor); // 今度は逆に「4ef420」を8ビットへ変換します // 0~1のRGBへクランプ Vector3 color2 = HexToClamp01(hexColor); // 8ビットカラーへ変換 int[] rgb2 = clamp01ToRgb(color2); // 「78, 244, 32」が返ります Console.WriteLine("RGB: " + rgb2[0] + ", " + rgb2[1] + ", " + rgb[2]); // HSVに変換 Vector3 hsv = RGB_TO_HSV(color2); Console.WriteLine("HSV: " + Math.Round(hsv.X * 360) + ", " + Math.Round(hsv.Y * 100) + ", " + Math.Round(hsv.Z * 100)); // HSVから16進数カラーへ Vector3 color3 = HSV_TO_RGB(hsv); string hexColor2 = clamp01ToHex(color3); Console.WriteLine("HEX: #" + hexColor2); Console.ReadKey(); } // 8ビットから0-1 static Vector3 rgbToClamp01(int[] rgb) { return new Vector3(rgb[0] / 255.0f, rgb[1] / 255.0f, rgb[2] / 255.0f); } // 0-1から8ビットへ static int[] clamp01ToRgb(Vector3 color) { int[] rgb = { (int)(color.X * 255), (int)(color.Y * 255), (int)(color.Z * 255) }; return rgb; } // 0-1カラーから16進数カラーへ static string clamp01ToHex(Vector3 color) { string[] hexTable = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; Vector3 rgb = color * 255; int[] num = new int[6]; string webColor = ""; num[0] = (int)Math.Floor(rgb.X / 16); num[1] = (int)Math.Floor(rgb.X % 16); num[2] = (int)Math.Floor(rgb.Y / 16); num[3] = (int)Math.Floor(rgb.Y % 16); num[4] = (int)Math.Floor(rgb.Z / 16); num[5] = (int)Math.Floor(rgb.Z % 16); for(int i = 0; i < 6; i++) { webColor += hexTable[num[i]]; } return webColor; } // 16進数カラーから0-1カラーへ static Vector3 HexToClamp01(string hexColor) { string[] hexTable = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; hexColor = hexColor.ToLower(); int[] str = new int[6]; for(int i = 0; i < 6; i++) { string num = hexColor.Substring(i, 1); for(int j = 0; j < hexTable.Length; j++) { if(hexTable[j] == num) { str[i] = j; break; } } } int red = str[0] * 16 +str[1]; int green = str[2] * 16 + str[3]; int blue = str[4] * 16 + str[5]; return new Vector3(red / 255.0f, green / 255.0f, blue / 255.0f); } // RGBからHSVへ変換 // 範囲は0 - 1 // 360で表すと、0:赤、60:黄、120:緑、180:水色、240:青、300:紫、360:赤 public static Vector3 RGB_TO_HSV(Vector3 rgb) { float hue = 0; float saturation = 0; float value = 0; float max = Math.Max(rgb.X, Math.Max(rgb.Y, rgb.Z)); float min = Math.Min(rgb.X, Math.Min(rgb.Y, rgb.Z)); // Hue if (max == min) { hue = 0; } else if (max == rgb.X) { hue = (rgb.Y - rgb.Z) / (max - min); } else if (max == rgb.Y) { hue = (rgb.Z - rgb.X) / (max - min) + 2; } else if (max == rgb.Z) { hue = (rgb.X - rgb.Y) / (max - min) + 4; } hue /= 6.0f; if (hue < 0) hue += 1.0f; // Saturation if (max == 0) { saturation = 0; } else { saturation = (max - min) / max; } // Value value = max; return new Vector3(hue, saturation, value); } // HSVからRGBへ変換 public static Vector3 HSV_TO_RGB(Vector3 hsv) { float red = 0; float green = 0; float blue = 0; if (hsv.Y == 0) { red = green = blue = hsv.Z; } else { if (hsv.X >= 1.0f) hsv.X -= 1.0f; hsv.X *= 6.0f; float i = (float)Math.Floor(hsv.X); float f = hsv.X - i; // 小数点以下を得る float p = hsv.Z * (1 - hsv.Y); float q = hsv.Z * (1 - (hsv.Y * f)); float t = hsv.Z * (1 - (hsv.Y * (1 - f))); if (i < 1) { red = hsv.Z; green = t; blue = p; } else if (i < 2) { red = q; green = hsv.Z; blue = p; } else if (i < 3) { red = p; green = hsv.Z; blue = t; } else if (i < 4) { red = p; green = q; blue = hsv.Z; } else if (i < 5) { red = t; green = p; blue = hsv.Z; } else { red = hsv.Z; green = p; blue = q; } } return new Vector3(red, green, blue); } }