Как изменить цвет RGB на HSV? На языке C#. Я ищу очень быстрый метод без какой-либо внешней библиотеки.
Что делать, чтобы адаптировать код из сообщения HSL для использования в решении HSV?
Википедия: оба математически цилиндрические, но HSV концептуально можно рассматривать как перевернутый конус цветов, HSL концептуально представляет собой двойной конус или сферу. Хотя «оттенок» в HSL и HSV относится к одному и тому же атрибуту, их определения «насыщенности» сильно различаются.
@ Адам: Я бы хотел, чтобы люди Paint.NET смогли это понять! :)
Повторное повторение: HSV сильно отличается от HSL. HSV иногда называют HSB (особенно в Photoshop и .NET).





Здесь есть реализация C:
http://www.cs.rit.edu/~ncs/color/t_convert.html
Преобразование в C# должно быть очень простым, так как почти не вызываются функции - только вычисления.
найдено через Google
Эта реализация неверна. Кажется, это на основе этого примера кода, но в нем отсутствует раздел (часть нормализации). Если бы я споткнулся на какое-то время!
Рассматривали ли вы простое использование пространства имен System.Drawing? Например:
System.Drawing.Color color = System.Drawing.Color.FromArgb(red, green, blue);
float hue = color.GetHue();
float saturation = color.GetSaturation();
float lightness = color.GetBrightness();
Обратите внимание, что это не совсем то, о чем вы просили (см. различия между HSL и HSV и класс Color не имеет обратного преобразования из HSL / HSV, но последний разумно легко добавить.
Как вы заметили, это на самом деле не отвечает на вопрос, потому что эти методы обеспечивают преобразование RGB в HSL, а не RGB в HSV.
@greg: Я согласен, это приведет к ужасным результатам, как я сам убедился.
-1: Поскольку это не ответ на вопрос. HSV сильно отличается от HSL. Примечание: HSV иногда называют HSB (особенно в Photoshop и .NET).
Я не уверен, в чем разница между легкостью, яркостью и ценностью (всегда думал, что это синонимы), но, глядя на реализацию System.Drawing.Color, я вижу, что она не основана на весах NTSC для красного, зеленого и синего, но рассматривает их все то же самое, что дает неоптимальные результаты.
@IanBoyd Хотя то, что вы говорите по поводу. HSV, HSL и HSB верны, проблема в том, что реализация HSB в System.Drawing, на самом деле, кажется неправильным: они реализовали HSL. В .NET API указано, что Color.GetBrightness()возвращает легкость, а не значение (т.е. это не «V» в HSV, а «L» в HSL).
Это версия VB.net, которая отлично работает для меня, перенесенная из кода C в сообщении BlaM.
There's a C implementation here:
http://www.cs.rit.edu/~ncs/color/t_convert.html
Should be very straightforward to convert to C#, as almost no functions are called - just > calculations.
Public Sub HSVtoRGB(ByRef r As Double, ByRef g As Double, ByRef b As Double, ByVal h As Double, ByVal s As Double, ByVal v As Double)
Dim i As Integer
Dim f, p, q, t As Double
If (s = 0) Then
' achromatic (grey)
r = v
g = v
b = v
Exit Sub
End If
h /= 60 'sector 0 to 5
i = Math.Floor(h)
f = h - i 'factorial part of h
p = v * (1 - s)
q = v * (1 - s * f)
t = v * (1 - s * (1 - f))
Select Case (i)
Case 0
r = v
g = t
b = p
Exit Select
Case 1
r = q
g = v
b = p
Exit Select
Case 2
r = p
g = v
b = t
Exit Select
Case 3
r = p
g = q
b = v
Exit Select
Case 4
r = t
g = p
b = v
Exit Select
Case Else 'case 5:
r = v
g = p
b = q
Exit Select
End Select
End Sub
Обратите внимание, что Color.GetSaturation() и Color.GetBrightness() возвращают значения HSL, а не HSV.
Следующий код демонстрирует разницу.
Color original = Color.FromArgb(50, 120, 200);
// original = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}
double hue;
double saturation;
double value;
ColorToHSV(original, out hue, out saturation, out value);
// hue = 212.0
// saturation = 0.75
// value = 0.78431372549019607
Color copy = ColorFromHSV(hue, saturation, value);
// copy = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}
// Compare that to the HSL values that the .NET framework provides:
original.GetHue(); // 212.0
original.GetSaturation(); // 0.6
original.GetBrightness(); // 0.490196079
Следующий код C# - это то, что вам нужно. Он преобразуется между RGB и HSV с использованием алгоритмов, описанных в Википедия. Диапазон значений: 0–360 для hue и 0–1 для saturation или value.
public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)
{
int max = Math.Max(color.R, Math.Max(color.G, color.B));
int min = Math.Min(color.R, Math.Min(color.G, color.B));
hue = color.GetHue();
saturation = (max == 0) ? 0 : 1d - (1d * min / max);
value = max / 255d;
}
public static Color ColorFromHSV(double hue, double saturation, double value)
{
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);
value = value * 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
if (hi == 0)
return Color.FromArgb(255, v, t, p);
else if (hi == 1)
return Color.FromArgb(255, q, v, p);
else if (hi == 2)
return Color.FromArgb(255, p, v, t);
else if (hi == 3)
return Color.FromArgb(255, p, q, v);
else if (hi == 4)
return Color.FromArgb(255, t, p, v);
else
return Color.FromArgb(255, v, p, q);
}
Я думаю, вы перенесли образцы значений насыщенности и значения в свой ответ. Когда я конвертирую rgb (50,120,200) в значение Hue-Saturation-Value (HSV), я получаю hsv (212, 75%, 78,4%). Глядя на формулы Википедии для HSV: V = Max (r, g, b). В этом случае max (50,120,200) = 200. 200/255 = 0,7843
я просто отредактирую ответ, транспонировав числа Saturation и Value. Насыщенность должна быть 0,75, значение должно быть 0,7843 ...
Есть идеи, как преобразовать насыщенность от 0 до 1 в значение насыщенности, которое использует MS Paint (например, шкала 0–240)?
Отличный ответ! Может быть, подумайте об использовании float вместо double, чтобы соответствовать тому, что возвращает .NET color.GetHue ()?
Не знаю, делаю ли я что-то не так, но эта пара функций мне не подходит. Выполнение ToHSV(FromHSV(32,1, 1)) возвращает 32, но ToHSV(FromHSV(33,1, 1)) возвращает 32.9411773. ToHSV(FromHSV(34,1, 1)) возвращает 33.8823547. ToHSV(FromHSV(35,1, 1)) возвращает 35.0588264. ToHSV(FromHSV(36,1, 1)) снова возвращает 36. Похоже, что кратные 4 работают правильно, в то время как другие смещены на кратные 1/17. Я понятия не имею, откуда взялось это магическое число.
Понятно. Переменные HSV используют тип double, который имеет гораздо более высокую степень детализации, чем те, которые могут содержать 8-битные каналы RGB. Поэтому 100% -ное двустороннее отображение невозможно. Однако мне интересно узнать, можно ли улучшить эти функции для безопасной работы с подмножеством RGB.
ПЕРВОЕ: убедитесь, что у вас есть цвет как растровое изображение, например:
Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
paintcolor = bmp.GetPixel(e.X, e.Y);
(e из обработчика событий, который выбрал мой цвет!)
То, что я сделал, когда у меня возникла эта проблема недавно, я сначала получил значения rgba (красный, зеленый, синий и альфа). Затем я создал 3 поплавка: оттенок, насыщенность и яркость. Затем вы просто делаете:
hue = yourcolor.Gethue;
saturation = yourcolor.GetSaturation;
brightness = yourcolor.GetBrightness;
Все выглядит так:
Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
paintcolor = bmp.GetPixel(e.X, e.Y);
float hue;
float saturation;
float brightness;
hue = paintcolor.GetHue();
saturation = paintcolor.GetSaturation();
brightness = paintcolor.GetBrightness();
Если теперь вы хотите отобразить их в ярлыке, просто выполните:
yourlabelname.Text = hue.ToString;
yourlabelname.Text = saturation.ToString;
yourlabelname.Text = brightness.ToString;
Вот и все, теперь у вас есть значения RGB в значениях HSV :)
Надеюсь это поможет
Это не HSV, а HSL. stackoverflow.com/questions/15668623/hsb-vs-hsl-vs-hsv
Не дубликат точный. HSL! = HSV.