在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
IntroductionWhy an article on "colors"? It's the same question I asked myself before writing this series. The fact is, in .NET, there are only two color formats that can be used: the RGB color model and the HSB color model. Those two are encapsulated in the It is largely sufficient for simple uses, like changing the background color of a component, but insufficient if we want to develop graphic tools (or something which implies conversion between color formats). I've started looking for other formats, like CMYK, when I was learning how to add cool design-time support to my custom controls. That's why I publish this series of 3 articles. The proposed article content will be as follows:
Let's start with some definitions"Color (or colour, see spelling differences) is the visual perceptual property corresponding in humans to the categories called red, yellow, white, etc. Color derives from the spectrum of light (distribution of light energy versus wavelength) interacting in the eye with the spectral sensitivities of the light receptors. Color categories and physical specifications of color are also associated with objects, materials, light sources, etc., based on their physical properties such as light absorption, reflection, or emission spectra." "Colorimetry is the science that describes colors in numbers, or provides a physical color match using a variety of measurement instruments. Colorimetry is used in chemistry, and in industries such as color printing, textile manufacturing, paint manufacturing and in the food industry." Colorimetry definition, Wikipedia. Then, how can we display colors as numbers? the answer: color models. I - Color models
A - RGB (Red Green Blue)
The RGB (Red, Green, Blue) color model is the most known, and the most used every day. It defines a color space in terms of three components:
The RGB color model is an additive one. In other words, Red, Green and Blue values (known as the three primary colors) are combined to reproduce other colors. Its common graphic representation is the following image:
In .NET, the Hide Copy Code
Console.WriteLine(String.Format("R={0}, G={1}, B={2}",
Color.Red.R, Color.Red.G, Color.Red.B);
Console.WriteLine(String.Format("R={0}, G={1}, B={2}",
Color.Cyan.R, Color.Cyan.G, Color.Cyan.B);
Console.WriteLine(String.Format("R={0}, G={1}, B={2}",
Color.White.R, Color.White.G, Color.White.B);
Console.WriteLine(String.Format("R={0}, G={1}, B={2}",
Color.SteelBlue.R, Color.SteelBlue.G, Color.SteelBlue.B);
// etc...
but this is not its only usage. For this reason, we can define a dedicated RGB structure for further coding, as shown below: Copy Code
/// <summary>
/// RGB structure.
/// </summary>
public struct RGB
{
/// <summary>
/// Gets an empty RGB structure;
/// </summary>
public static readonly RGB Empty = new RGB();
private int red;
private int green;
private int blue;
public static bool operator ==(RGB item1, RGB item2)
{
return (
item1.Red == item2.Red
&& item1.Green == item2.Green
&& item1.Blue == item2.Blue
);
}
public static bool operator !=(RGB item1, RGB item2)
{
return (
item1.Red != item2.Red
|| item1.Green != item2.Green
|| item1.Blue != item2.Blue
);
}
/// <summary>
/// Gets or sets red value.
/// </summary>
public int Red
{
get
{
return red;
}
set
{
red = (value>255)? 255 : ((value<0)?0 : value);
}
}
/// <summary>
/// Gets or sets red value.
/// </summary>
public int Green
{
get
{
return green;
}
set
{
green = (value>255)? 255 : ((value<0)?0 : value);
}
}
/// <summary>
/// Gets or sets red value.
/// </summary>
public int Blue
{
get
{
return blue;
}
set
{
blue = (value>255)? 255 : ((value<0)?0 : value);
}
}
public RGB(int R, int G, int B)
{
this.red = (R>255)? 255 : ((R<0)?0 : R);
this.green = (G>255)? 255 : ((G<0)?0 : G);
this.blue = (B>255)? 255 : ((B<0)?0 : B);
}
public override bool Equals(Object obj)
{
if(obj==null || GetType()!=obj.GetType()) return false;
return (this == (RGB)obj);
}
public override int GetHashCode()
{
return Red.GetHashCode() ^ Green.GetHashCode() ^ Blue.GetHashCode();
}
}
B - HSB color spaceThe HSB (Hue, Saturation, Brightness) color model defines a color space in terms of three constituent components:
Its common graphic representation is the following image:
The HSB model is also known as HSV (Hue, Saturation, Value) model. The HSV model was created in 1978 by Alvy Ray Smith. It is a nonlinear transformation of the RGB color space. In other words, color is not defined as a simple combination (addition/substraction) of primary colors but as a mathematical transformation. Note: HSV and HSB are the same, but HSL is different. All this said, a HSB structure can be : Copy Code
/// <summary>
/// Structure to define HSB.
/// </summary>
public struct HSB
{
/// <summary>
/// Gets an empty HSB structure;
/// </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>
/// Gets or sets the hue component.
/// </summary>
public double Hue
{
get
{
return hue;
}
set
{
hue = (value>360)? 360 : ((value<0)?0:value);
}
}
/// <summary>
/// Gets or sets saturation component.
/// </summary>
public double Saturation
{
get
{
return saturation;
}
set
{
saturation = (value>1)? 1 : ((value<0)?0:value);
}
}
/// <summary>
/// Gets or sets the brightness component.
/// </summary>
public double Brightness
{
get
{
return brightness;
}
set
{
brightness = (value>1)? 1 : ((value<0)? 0 : value);
}
}
/// <summary>
/// Creates an instance of a HSB structure.
/// </summary>
/// <param name="h">Hue value.</param>
/// <param name="s">Saturation value.</param>
/// <param name="b">Brightness value.</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();
}
}
C - HSL color spaceThe HSL color space, also called HLS or HSI, stands for:
Its common graphic representation is the following image:
HSL is similar to HSB. The main difference is that HSL is symmetrical to lightness and darkness. This means that:
For my part, HSL offers a more accurate (even if it's not absolute) color approximation than HSB. All this said, a HSL structure can be: Copy Code
/// <summary>
/// Structure to define HSL.
/// </summary>
public struct HSL
{
/// <summary>
/// Gets an empty HSL structure;
/// </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>
/// Gets or sets the hue component.
/// </summary>
public double Hue
{
get
{
return hue;
}
set
{
hue = (value>360)? 360 : ((value<0)?0:value);
}
}
/// <summary>
/// Gets or sets saturation component.
/// </summary>
public double Saturation
{
get
{
return saturation;
}
set
{
saturation = (value>1)? 1 : ((value<0)?0:value);
}
}
/// <summary>
/// Gets or sets the luminance component.
/// </summary>
public double Luminance
{
get
{
return luminance;
}
set
{
luminance = (value>1)? 1 : ((value<0)? 0 : value);
}
}
/// <summary>
/// Creates an instance of a HSL structure.
/// </summary>
/// <param name="h">Hue value.</param>
/// <param name="s">Saturation value.</param>
/// <param name="l">Lightness value.</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();
}
}
D - CMYK color spaceThe CMYK color space, also known as CMJN, stands for:
It is a subtractive color model used in color printing. CMYK works on an optical illusion that is based on light absorption. Its common graphic representation is the following image:
Like the RGB color model, CMYK is a combination of primary colors (cyan, magenta, yellow and black). It is, probably, the only thing they have in common. Why using this model? Why black is used? you can tell me... Well it's only for practical purpose. Wikipedia said:
Let's come back to our reality. A CMYK structure can be: Copy Code
/// <summary>
/// Structure to define CMYK.
/// </summary>
public struct CMYK
{
/// <summary>
/// Gets an empty CMYK structure;
/// </summary>
public readonly static CMYK Empty = new CMYK();
private double c;
private double m;
private double y;
private double k;
public static bool operator ==(CMYK item1, CMYK item2)
{
return (
item1.Cyan == item2.Cyan
&& item1.Magenta == item2.Magenta
&& item1.Yellow == item2.Yellow
&& item1.Black == item2.Black
);
}
public static bool operator !=(CMYK item1, CMYK item2)
{
return (
item1.Cyan != item2.Cyan
|| item1.Magenta != item2.Magenta
|| item1.Yellow != item2.Yellow
|| item1.Black != item2.Black
);
}
public double Cyan
{
get
{
return c;
}
set
{
c = value;
c = (c>1)? 1 : ((c<0)? 0 : c);
}
}
public double Magenta
{
get
{
return m;
}
set
{
m = value;
m = (m>1)? 1 : ((m<0)? 0 : m);
}
}
public double Yellow
{
get
{
return y;
}
set
{
y = value;
y = (y>1)? 1 : ((y<0)? 0 : y);
}
}
public double Black
{
get
{
return k;
}
set
{
k = value;
k = (k>1)? 1 : ((k<0)? 0 : k);
}
}
/// <summary>
/// Creates an instance of a CMYK structure.
/// </summary>
public CMYK(double c, double m, double y, double k)
{
this.c = c;
this.m = m;
this.y = y;
this.k = k;
}
public override bool Equals(Object obj)
{
if(obj==null || GetType()!=obj.GetType()) return false;
return (this == (CMYK)obj);
}
public override int GetHashCode()
{
return Cyan.GetHashCode() ^
Magenta.GetHashCode() ^ Yellow.GetHashCode() ^ Black.GetHashCode();
}
}
E - YUV color spaceThe YUV model defines a color space in terms of one luma and two chrominance components. The YUV color model is used in the PAL, NTSC, and SECAM composite color video standards. The YUV color space stands for:
A graphic representation is the following image:
A YUV structure can be: Copy Code
/// <summary>
/// Structure to define YUV.
/// </summary>
public struct YUV
{
/// <summary>
/// Gets an empty YUV structure.
/// </summary>
public static readonly YUV Empty = new YUV();
private double y;
private double u;
private double v;
public static bool operator ==(YUV item1, YUV item2)
{
return (
item1.Y == item2.Y
&& item1.U == item2.U
&& item1.V == item2.V
);
}
public static bool operator !=(YUV item1, YUV item2)
{
return (
item1.Y != item2.Y
|| item1.U != item2.U
|| item1.V != item2.V
);
}
public double Y
{
get
{
return y;
}
set
{
y = value;
y = (y>1)? 1 : ((y<0)? 0 : y);
}
}
public double U
{
get
{
return u;
}
set
{
u = value;
u = (u>0.436)? 0.436 : ((u<-0.436)? -0.436 : u);
}
}
public double V
{
get
{
return v;
}
set
{
v = value;
v = (v>0.615)? 0.615 : ((v<-0.615)? -0.615 : v);
}
}
/// <summary>
/// Creates an instance of a YUV structure.
/// </summary>
public YUV(double y, double u, double v)
{
this.y = (y>1)? 1 : ((y<0)? 0 : y);
this.u = (u>0.436)? 0.436 : ((u<-0.436)? -0.436 : u);
this.v = (v>0.615)? 0.615 : ((v<-0.615)? -0.615 : v);
}
public override bool Equals(Object obj)
{
if(obj==null || GetType()!=obj.GetType()) return false;
return (this == (YUV)obj);
}
public override int GetHashCode()
{
return Y.GetHashCode() ^ U.GetHashCode() ^ V.GetHashCode();
}
}
F - CIE XYZ color spaceIn opposition to the previous models, the CIE XYZ model defines an absolute color space. It is also known as the CIE 1931 XYZ color space and stands for:
Before trying to explain why I include this color space in this article, you have to know that it's one of the first standards created by the International Commission on Illumination (CIE) in 1931. It is based on direct measurements of the human eye, and serves as the basis from which many other color spaces are defined. A graphic representation is the following image:
A CIE XYZ structure can be: Copy Code
/// <summary>
/// Structure to define CIE XYZ.
/// </summary>
public struct CIEXYZ
{
/// <summary>
/// Gets an empty CIEXYZ structure.
/// </summary>
public static readonly CIEXYZ Empty = new CIEXYZ();
/// <summary>
/// Gets the CIE D65 (white) structure.
/// </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>
/// Gets or sets X component.
/// </summary>
public double X
{
get
{
return this.x;
}
set
{
this.x = (value>0.9505)? 0.9505 : ((value<0)? 0 : value);
}
}
/// <summary>
/// Gets or sets Y component.
/// </summary>
public double Y
{
get
{
return this.y;
}
set
{
this.y = (value>1.0)? 1.0 : ((value<0)?0 : value);
}
}
/// <summary>
/// Gets or sets Z component.
/// </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();
}
}
Well! why do I have to include this model? I have made a quick research to include Cie L*a*b* color model in this article, and I find that a conversion to an absolute color space is required before converting to L*a*b*. The model used in the conversion principle is Cie XYZ. So, I've included it and now everyone can understand "what are those XYZ values" used further in the article.
G - CIE L*a*b* color space"A Lab color space is a color-opponent space with dimension L for luminance and a and b for the color-opponent dimensions, based on nonlinearly-compressed CIE XYZ color space coordinates." As said in the previous definition, CIE L*a*b* color space, also know as CIE 1976 color space, stands for:
The L*a*b* color model has been created to serve as a device independent model to be used as a reference. It is based directly on the CIE 1931 XYZ color space as an attempt to linearize the perceptibility of color differences. The non-linear relations for L*, a*, and b* are intended to mimic the logarithmic response of the eye, coloring information is referred to the color of the white point of the system. A CIE L*a*b* structure can be: Copy Code
/// <summary>
/// Structure to define CIE L*a*b*.
/// </summary>
public struct CIELab
{
全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论