Манипулирование цветами в .NET – часть первая - Пространство цветов HSB И HSL

ОГЛАВЛЕНИЕ

Пространство цветов HSB

Цветовая модель HSB (тон, насыщенность, яркость) определяет пространство цветов в виде трех составных компонентов:
• Тон: тип цвета (скажем, красный, синий или желтый).
     o Изменяется от 0 до 360° в большинстве приложений (каждое значение соответствует одному цвету: 0 - красный, 45 – оттенок оранжевого, а 55 – оттенок желтого).
• Насыщенность: интенсивность цвета.
     o Изменяется от 0 до 100% (0 значит бесцветный, то есть оттенок серого между черным и белым; 100 значит интенсивный цвет).
     o Также иногда называется "чистота" по аналогии с цветометрическими величинами «условная чистота».
• Яркость (или значение): яркость цвета.
     o Изменяется от 0 до 100% (0 – всегда черный; в зависимости от насыщенности, 100 может быть белым или более или менее насыщенным цветом).

Ее типичным графическим представлением является следующее изображение:

Модель HSB иначе называется моделью HSV (тон, насыщенность, значение). Модель HSV была создана в 1978 г. Элви Рэем Смитом. Это нелинейное преобразование пространства цветов RGB. Иначе говоря, цвет определяется не как простая комбинация (сложение/вычитание) основных цветов, а как математическое преобразование.

Замечание: HSV и HSB тождественны, но HSL отличается.

Структура HSB выглядит так:

/// <summary>
/// структура для определения HSB.
/// </summary>
public struct HSB
{
/// <summary>
/// получает пустую структуру HSB;
/// </summary>
public static readonly HSB Empty = new HSB();

private double hue;
private double saturation;
private double brightness;

public static bool operator ==(HSB item1, HSB item2)
{
return (
item1.Hue == item2.Hue
&& item1.Saturation == item2.Saturation
&& item1.Brightness == item2.Brightness
);
}

public static bool operator !=(HSB item1, HSB item2)
{
return (
item1.Hue != item2.Hue
|| item1.Saturation != item2.Saturation
|| item1.Brightness != item2.Brightness
);
}

/// <summary>
/// получает или устанавливает компонент тона.
/// </summary>
public double Hue
{
get
{
return hue;
}
set
{
hue = (value>360)? 360 : ((value<0)?0:value);
}
}

/// <summary>
/// получает или устанавливает компонент насыщенности.
/// </summary>
public double Saturation
{
get
{
return saturation;
}
set
{
saturation = (value>1)? 1 : ((value<0)?0:value);
}
}

/// <summary>
/// получает или устанавливает компонент яркости.
/// </summary>
public double Brightness
{
get
{
return brightness;
}
set
{
brightness = (value>1)? 1 : ((value<0)? 0 : value);
}
}

/// <summary>
/// создает экземпляр структуры HSB.
/// </summary>
/// <param name="h">значение тона.</param>
/// <param name="s">значение насыщенности.</param>
/// <param name="b">значение яркости.</param>
public HSB(double h, double s, double b)
{
hue = (h>360)? 360 : ((h<0)?0:h);
saturation = (s>1)? 1 : ((s<0)?0:s);
brightness = (b>1)? 1 : ((b<0)?0:b);
}

public override bool Equals(Object obj)
{
if(obj==null || GetType()!=obj.GetType()) return false;

return (this == (HSB)obj);
}

public override int GetHashCode()
{
return Hue.GetHashCode() ^ Saturation.GetHashCode() ^
Brightness.GetHashCode();
}
}

Пространство цветов HSL

Пространство цветов HSL, иначе называемое HLS или HSI, означает:
• Тон: тип цвета (скажем, красный, синий или желтый).
     o Изменяется от 0 до 360° в большинстве приложений (каждое значение соответствует одному цвету: 0 - красный, 45 – оттенок оранжевого, а 55 – оттенок желтого).
• Насыщенность: изменение цвета в зависимости от светлоты.
     o Изменяется от 0 до 100% (от центра оси черного и белого).
• Светлота (также яркость, или светимость, или интенсивность).
     o Изменяется от 0 to 100% (от черного до белого).

Ее типичным графическим представлением является следующее изображение:

HSL похожа на HSB. Главное отличие в том, что HSL симметрична по отношению к светлоте и темноте.

Отсюда следует, что:
• В HSL компонент насыщенности всегда меняется от полностью насыщенного цвета до эквивалентного серого (в HSB, при B в максимуме, он меняется от насыщенного цвета до белого).
• В HSL светлота всегда покрывает весь спектр от черного через выбранный тон до белого (в HSB компонент B проходит лишь половину этого пути – от черного до выбранного тона).

HSL обеспечивает более точное (даже если оно не абсолютное) приближение цвета, чем HSB.
Структура HSL выглядит так:

/// <summary>
/// структура для определения HSL.
/// </summary>
public struct HSL
{
/// <summary>
/// получает пустую структуру HSL;
/// </summary>
public static readonly HSL Empty = new HSL();

private double hue;
private double saturation;
private double luminance;

public static bool operator ==(HSL item1, HSL item2)
{
return (
item1.Hue == item2.Hue
&& item1.Saturation == item2.Saturation
&& item1.Luminance == item2.Luminance
);
}

public static bool operator !=(HSL item1, HSL item2)
{
return (
item1.Hue != item2.Hue
|| item1.Saturation != item2.Saturation
|| item1.Luminance != item2.Luminance
);
}

/// <summary>
/// получает или устанавливает компонент тона.
/// </summary>
public double Hue
{
get
{
return hue;
}
set
{
hue = (value>360)? 360 : ((value<0)?0:value);
}
}

/// <summary>
/// получает или устанавливает компонент насыщенности.
/// </summary>
public double Saturation
{
get
{
return saturation;
}
set
{
saturation = (value>1)? 1 : ((value<0)?0:value);
}
}

/// <summary>
/// получает или устанавливает компонент яркости.
/// </summary>
public double Luminance
{
get
{
return luminance;
}
set
{
luminance = (value>1)? 1 : ((value<0)? 0 : value);
}
}

/// <summary>
/// создает экземпляр структуры HSL.
/// </summary>
/// <param name="h">значение тона.</param>
/// <param name="s">значение насыщенности.</param>
/// <param name="l">значение светлоты.</param>
public HSL(double h, double s, double l)
{
this.hue = (h>360)? 360 : ((h<0)?0:h);
this.saturation = (s>1)? 1 : ((s<0)?0:s);
this.luminance = (l>1)? 1 : ((l<0)?0:l);
}

public override bool Equals(Object obj)
{
if(obj==null || GetType()!=obj.GetType()) return false;

return (this == (HSL)obj);
}

public override int GetHashCode()
{
return Hue.GetHashCode() ^ Saturation.GetHashCode() ^
Luminance.GetHashCode();
}
}