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

ОГЛАВЛЕНИЕ

Преобразования XYZ

a - XYZ в RGB

Правило преобразования приведено ниже:

a = 0.055

затем

Эквивалент на C# следующий:

/// <summary>
/// преобразует CIEXYZ в структуру RGB.
/// </summary>
public static RGB XYZtoRGB(double x, double y, double z)
{
double[] Clinear = new double[3];
Clinear[0] = x*3.2410 - y*1.5374 - z*0.4986; // красный
Clinear[1] = -x*0.9692 + y*1.8760 - z*0.0416; // зеленый
Clinear[2] = x*0.0556 - y*0.2040 + z*1.0570; // синий

for(int i=0; i<3; i++)
{
Clinear[i] = (Clinear[i]<=0.0031308)? 12.92*Clinear[i] : (
1+0.055)* Math.Pow(Clinear[i], (1.0/2.4)) - 0.055;
}

return new RGB(
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}",
Clinear[0]*255.0)) ),
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}",
Clinear[1]*255.0)) ),
Convert.ToInt32( Double.Parse(String.Format("{0:0.00}",
Clinear[2]*255.0)) )
);
}

b - XYZ в L*a*b*

Правило преобразования приведено ниже:

Xn, Yn и Zn – цветовые координаты CIE XYZ эталонной белой точки.

Эквивалент на C# следующий:

/// <summary>
/// функция преобразования XYZ в L*a*b*.
/// </summary>
private static double Fxyz(double t)
{
return ((t > 0.008856)? Math.Pow(t, (1.0/3.0)) : (7.787*t + 16.0/116.0));
}

/// <summary>
/// преобразует CIEXYZ в CIELab.
/// </summary>
public static CIELab XYZtoLab(double x, double y, double z)
{
CIELab lab = CIELab.Empty;

lab.L = 116.0 * Fxyz( y/CIEXYZ.D65.Y ) -16;
lab.A = 500.0 * (Fxyz( x/CIEXYZ.D65.X ) - Fxyz( y/CIEXYZ.D65.Y) );
lab.B = 200.0 * (Fxyz( y/CIEXYZ.D65.Y ) - Fxyz( z/CIEXYZ.D65.Z) );

return lab;
}

Преобразования L*a*b*

a - L*a*b* в XYZ

Правило преобразования приведено ниже:

Эквивалент на C# следующий:

/// <summary>
/// преобразует CIELab в CIEXYZ.
/// </summary>
public static CIEXYZ LabtoXYZ(double l, double a, double b)
{
double delta = 6.0/29.0;

double fy = (l+16)/116.0;
double fx = fy + (a/500.0);
double fz = fy - (b/200.0);

return new CIEXYZ(
(fx > delta)? CIEXYZ.D65.X * (fx*fx*fx) : (fx - 16.0/116.0)*3*(
delta*delta)*CIEXYZ.D65.X,
(fy > delta)? CIEXYZ.D65.Y * (fy*fy*fy) : (fy - 16.0/116.0)*3*(
delta*delta)*CIEXYZ.D65.Y,
(fz > delta)? CIEXYZ.D65.Z * (fz*fz*fz) : (fz - 16.0/116.0)*3*(
delta*delta)*CIEXYZ.D65.Z
);
}

b - L*a*b* в RGB

Ничего нового: правило преобразования заключается в преобразовании в XYZ, а затем в RGB:

/// <summary>
/// преобразует CIELab в RGB.
/// </summary>
public static RGB LabtoRGB(double l, double a, double b)
{
return XYZtoRGB( LabtoXYZ(l, a, b) );
}

Использование кода

После изложения алгоритмов преобразования, возможно, больше рассказать нечего.

На самом деле, в ColorSpaceHelper есть много других полезных методов, в том числе:
• Реализация усредненного цвета (ColorSpaceHelper.GetColorDistance()).
• Генерация цветового круга (ColorSpaceHelper.GetWheelColors()) с поддержкой 32бит (альфа).
• Генерация цвета спектра света для (ColorSpaceHelper.GetSpectrumColors())с поддержкой 32бит (альфа).
• Преобразование в и из веб-цветов (ColorSpaceHelper.HexToColor()).
• Преобразование в и из System.Drawing.Color и других структур.

Интересные особенности

Как сказано ранее, есть много форматов. Статья дает пример полезности применения распространенных цветовых моделей (RGB,HSL, HSB, etc.) для проектов.

Ниже приведено предварительное изображение того, что можно сделать (и что будет показано в следующей статье) с помощью ColorSpaceHelper: