Манипулирование цветами в .NET – часть первая - Пространство цветов CIE XYZ и CIE L*a*b*

ОГЛАВЛЕНИЕ

Пространство цветов CIE XYZ

В отличие от предыдущих моделей, модель CIE XYZ определяет абсолютное пространство цветов. Оно иначе называется пространством цветов CIE 1931 XYZ и означает:
• X, сравниваемый с красным
     o Изменяется от 0 до 0.9505
• Y, сравниваемый с зеленым
     o Изменяется от 0 до 1.0
• Z, сравниваемый с синим
     o Изменяется от 0 до 1.089

Прежде чем объяснить, почему это пространство цветов было включено в статью, надо знать, что оно является одним из первых стандартов, созданных Международной комиссией по освещению (CIE) в 1931г.. Оно основано на непосредственных измерениях человеческого глаза и служит основой для определения множества других пространств цветов.

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

Структура CIE XYZ следующая:

/// <summary>
/// структура для определения CIE XYZ.
/// </summary>
public struct CIEXYZ
{
/// <summary>
/// получает пустую структуру CIEXYZ.
/// </summary>
public static readonly CIEXYZ Empty = new CIEXYZ();
/// <summary>
/// получает структуру CIE D65 (белый).
/// </summary>
public static readonly CIEXYZ D65 = new CIEXYZ(0.9505, 1.0, 1.0890);


private double x;
private double y;
private double z;

public static bool operator ==(CIEXYZ item1, CIEXYZ item2)
{
return (
item1.X == item2.X
&& item1.Y == item2.Y
&& item1.Z == item2.Z
);
}

public static bool operator !=(CIEXYZ item1, CIEXYZ item2)
{
return (
item1.X != item2.X
|| item1.Y != item2.Y
|| item1.Z != item2.Z
);
}

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

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

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

public CIEXYZ(double x, double y, double z)
{
this.x = (x>0.9505)? 0.9505 : ((x<0)? 0 : x);
this.y = (y>1.0)? 1.0 : ((y<0)? 0 : y);
this.z = (z>1.089)? 1.089 : ((z<0)? 0 : z);
}

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

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

public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
}

}

Так почему была включена эта модель?

Было проведено краткое исследование для включения цветовой модели Cie L*a*b* в эту статью, и оказалось, что требуется преобразование в абсолютное пространство цветов перед преобразованием в L*a*b*. В правиле преобразования используется модель Cie XYZ. Поэтому оно было включено, чтобы всем было понятно, что означают значения XYZ, используемые дальше в статье.

Пространство цветов CIE L*a*b*

Лабораторное пространство цветов является цветоппонентным пространством с измерением L для яркости и a и b для цветоппонентных измерений, основанных на нелинейно сжатых координатах пространства цветов CIE XYZ.

Как сказано в предыдущем определении, пространство цветов CIE L*a*b*, иначе называемое пространством цветов CIE 1976, означает:
• L*, яркость
• a*, красное/зеленое цветоппонентное измерение
• b*, желтое/синее цветоппонентное измерение

Цветовая модель L*a*b* была создана, чтобы служить в качестве аппаратно-независимой модели, используемой как эталон. Она основана непосредственно на пространстве цветов CIE 1931 XYZ для линеаризации воспринимаемости цветовых различий.

Нелинейные соотношения для L*, a* и b* имитируют логарифмическую реакцию глаза, информация о цвете ссылается на цвет белой точки системы.

Структура CIE L*a*b* следующая:

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

private double l;
private double a;
private double b;


public static bool operator ==(CIELab item1, CIELab item2)
{
return (
item1.L == item2.L
&& item1.A == item2.A
&& item1.B == item2.B
);
}

public static bool operator !=(CIELab item1, CIELab item2)
{
return (
item1.L != item2.L
|| item1.A != item2.A
|| item1.B != item2.B
);
}


/// <summary>
/// получает или устанавливает компонент L.
/// </summary>
public double L
{
get
{
return this.l;
}
set
{
this.l = value;
}
}

/// <summary>
/// получает или устанавливает компонент a.
/// </summary>
public double A
{
get
{
return this.a;
}
set
{
this.a = value;
}
}

/// <summary>
/// получает или устанавливает компонент a.
/// </summary>
public double B
{
get
{
return this.b;
}
set
{
this.b = value;
}
}

public CIELab(double l, double a, double b)
{
this.l = l;
this.a = a;
this.b = b;
}

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

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

public override int GetHashCode()
{
return L.GetHashCode() ^ a.GetHashCode() ^ b.GetHashCode();
}

}

Есть еще много других форматов типа RYB и CcMmYK, но нет цели создать каркас цветов.