原文:Win8 Metro(C#)数字图像处理--4图像颜色空间描述



图像颜色空间是图像颜色集合的数学表示,本小节将针对几种常见颜色空间做个简单介绍。

       /// <summary>
/// Get rgba value from source image.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static byte[] RGBValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
byte[] rgbaValue = new byte[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
rgbaValue[x * 3 + y * w * 3] = (byte)temp[x * 4 + y * w * 4];
rgbaValue[x * 3 + 1 + y * w * 3] = (byte)temp[x * 4 + 1 + y * w * 4];
rgbaValue[x * 3 + 2 + y * w * 3] = (byte)temp[x * 4 + 2 + y * w * 4];
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return rgbaValue;
}
else
{
return null;
}
}

4.2 XYZ颜色空间

[空间解析]

XYZ颜色空间:国际照明委员会(CIE)在进行了大量正常人视觉测量和统计,1931年建立了“标准色度观察者”, 从而奠定了现代CIE标准色度学的定量基础。由于"标准色度观察者"用来标定光谱色时出现负 刺激值,计算不便,也不易理解,因此1931年CIE在RGB系统基础上,改用三个假想的原色X、Y、 Z建立了一个新的色度系统。将它匹配等能光谱的三刺激值,定名为"CIE1931 标准色度观察者 光谱三刺激值",简称为"CIE1931标准色度观察者"。这一系统叫做"CIE1931标准色度系统"或称为“2”视场XYZ色度系统"。其中Y表示亮度,X、Y反映颜色的色度特性,色度图如下所示。

        /// <summary>
/// Get XYZ value from source image.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] XYZValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] xyzValue = new double[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = temp[x * 4 + y * w * 4];
g = temp[x * 4 + 1 + y * w * 4];
r = temp[x * 4 + 2 + y * w * 4];
xyzValue[x * 3 + y * w * 3] = (double)(0.5767309 * (double)r + 0.1855540 * (double)g + 0.1881852 * (double)b);
xyzValue[x * 3 + 1 + y * w * 3] = (double)(0.2973769 * (double)r + 0.6273491 * (double)g + 0.0752741 * (double)b);
xyzValue[x * 3 + 2 + y * w * 3] = (double)(0.0270343 * (double)r + 0.0706872 * (double)g + 0.9911085 * (double)b);
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return xyzValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert rgb to xyz.
/// </summary>
/// <param name="rgbValue">The rgb value.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoXYZ(byte[]rgbValue,int w,int h)
{
if (rgbValue != null)
{
double[] xyzValue = new double[w * h * 3];
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = rgbValue[x * 3 + y * w * 3];
g = rgbValue[x * 3 + 1 + y * w * 3];
r = rgbValue[x * 3 + 2 + y * w * 3];
xyzValue[x * 3 + y * w * 3] = (double)(0.5767309 * (double)r + 0.1855540 * (double)g + 0.1881852 * (double)b);
xyzValue[x * 3 + 1 + y * w * 3] = (double)(0.2973769 * (double)r + 0.6273491 * (double)g + 0.0752741 * (double)b);
xyzValue[x * 3 + 2 + y * w * 3] = (double)(0.0270343 * (double)r + 0.0706872 * (double)g + 0.9911085 * (double)b);
}
}
return xyzValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert xyz to rgb.
/// </summary>
/// <param name="xyzValue">The xyz value.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] XYZtoRGB(byte[] xyzValue, int w, int h)
{
if (xyzValue != null)
{
double[] rgbValue = new double[w * h * 3];
double xV = 0, yV = 0, zV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
xV = xyzValue[x * 3 + y * w * 3];
yV = xyzValue[x * 3 + 1 + y * w * 3];
zV = xyzValue[x * 3 + 2 + y * w * 3];
rgbValue[x * 3 + y * w * 3] = (byte)(0.0134474 * xV - 0.1183897 * yV + 1.0154096 * zV);
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(-0.9692660 * xV + 1.8760108 * yV + 0.0415560 * zV);
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(2.0413690 * xV - 0.5649464 * yV - 0.3446944 * zV);
}
}
return rgbValue;
}
else
{
return null;
}
}


        /// <summary>
/// Get yuv information.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] YUVValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] yuvValue = new double[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = temp[x * 4 + y * w * 4];
g = temp[x * 4 + 1 + y * w * 4];
r = temp[x * 4 + 2 + y * w * 4];
yuvValue[x * 3 + y * w * 3] = (double)(0.299 * (double)r + 0.587 * (double)g + 0.114 * (double)b);
yuvValue[x * 3 + 1 + y * w * 3] = (double)(-0.148 * (double)r - 0.289 * (double)g + 0.437 * (double)b);
yuvValue[x * 3 + 2 + y * w * 3] = (double)(0.615 * (double)r - 0.515 * (double)g - 0.100 * (double)b);
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return yuvValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert RGB to YUV.
/// </summary>
/// <param name="rgbValue">The rgb information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoYUV(byte[] rgbValue, int w, int h)
{
if (rgbValue != null)
{
double[] yuvValue = new double[w * h * 3];
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = rgbValue[x * 3 + y * w * 3];
g = rgbValue[x * 3 + 1 + y * w * 3];
r = rgbValue[x * 3 + 2 + y * w * 3];
yuvValue[x * 3 + y * w * 3] = (double)(0.299 * (double)r + 0.587 * (double)g + 0.114 * (double)b);
yuvValue[x * 3 + 1 + y * w * 3] = (double)(-0.148 * (double)r - 0.289 * (double)g + 0.437 * (double)b);
yuvValue[x * 3 + 2 + y * w * 3] = (double)(0.615 * (double)r - 0.515 * (double)g - 0.100 * (double)b);
}
}
return yuvValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert yuv to rgb.
/// </summary>
/// <param name="yuvValue">The yuv information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] YUVtoRGB(byte[] yuvValue, int w, int h)
{
if (yuvValue != null)
{
double[] rgbValue = new double[w * h * 3];
double yV = 0, uV = 0, vV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
yV = yuvValue[x * 3 + y * w * 3];
uV = yuvValue[x * 3 + 1 + y * w * 3];
vV = yuvValue[x * 3 + 2 + y * w * 3];
rgbValue[x * 3 + y * w * 3] = (byte)(1 * yV + 2.032 * uV + 0 * vV);
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(1 * yV - 0.395 * uV - 0.581 * vV);
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(1 * yV + 0 * uV + 1.140 * vV);
}
}
return rgbValue;
}
else
{
return null;
}
}

4.4 HIS颜色空间

 [空间解析]

  HIS颜色空间是从人的视觉系统出发,用色调(Hue)、色饱和度(Saturation或Chroma)和亮度 (Intensity或Brightness)来描述色彩。HSI色彩空间可以用一个圆锥空间模型来描述。用这种 描述HIS色彩空间的圆锥模型相当复杂,但确能把色调、亮度和色饱和度的变化情形表现得很清楚。通常把色调和饱和度通称为色度,用来表示颜色的类别与深浅程度,H和S包含了颜色信息,而I则与颜色信息无关。

  HIS颜色空间模型如下图所示:

        /// <summary>
/// Get his information.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] HISValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] hisValue = new double[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
double r = 0, g = 0, b = 0;
double hV = 0, degree = 0, iV = 0, sV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = (double)temp[x * 4 + y * w * 4]/255.0;
g = (double)temp[x * 4 + 1 + y * w * 4]/255.0;
r = (double)temp[x * 4 + 2 + y * w * 4]/255.0;
degree = Math.Acos(0.5 * ((r - g) + (r - b)) / Math.Sqrt((r - g) * (r - g) + (r - b) * (g - b) + 0.0000001)) / (2 * Math.PI);
hV = (b <= g) ? degree : 1.0 - degree;
iV = (double)(r + g + b) / 3.0;
sV = 1.0 - 3.0 * (double)Math.Min(r, Math.Min(g, b)) / (double)(r + g + b + 0.00000001);
hisValue[x * 3 + y * w * 3] = hV;
hisValue[x * 3 + 1 + y * w * 3] = iV;
hisValue[x * 3 + 2 + y * w * 3] = sV;
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return hisValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert rgb to his.
/// </summary>
/// <param name="rgbValue">The rgb information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoHIS(byte[] rgbValue, int w, int h)
{
if (rgbValue != null)
{
double[] hisValue = new double[w * h * 3];
double r = 0, g = 0, b = 0;
double hV = 0, degree = 0, iV = 0, sV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = (double)rgbValue[x * 3 + y * w * 3]/255.0;
g = (double)rgbValue[x * 3 + 1 + y * w * 3]/255.0;
r = (double)rgbValue[x * 3 + 2 + y * w * 3]/255.0;
degree = Math.Acos(0.5 * ((r - g) + (r - b)) / Math.Sqrt((r - g) * (r - g) + (r - b) * (g - b) + 0.0000001)) / (2 * Math.PI);
hV = (b <= g) ? degree : 1.0 - degree;
iV = (double)(r + g + b) / 3.0;
sV = 1.0 - 3.0 * (double)Math.Min(r, Math.Min(g, b)) / (double)(r + g + b + 0.00000001);
hisValue[x * 3 + y * w * 3] = hV;
hisValue[x * 3 + 1 + y * w * 3] = iV;
hisValue[x * 3 + 2 + y * w * 3] = sV;
}
}
return hisValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert his to rgb.
/// </summary>
/// <param name="hisValue">The his information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] HIStoRGB(byte[] hisValue, int w, int h)
{
if (hisValue != null)
{
double[] rgbValue = new double[w * h * 3];
double hV = 0, iV = 0, sV = 0;
double r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
hV = hisValue[x * 3 + y * w * 3];
iV = hisValue[x * 3 + 1 + y * w * 3];
sV = hisValue[x * 3 + 2 + y * w * 3];
hV = hV * 2 * Math.PI;
if (hV >= 0 && hV < 2 * Math.PI / 3)
{
r = (double)(iV * (1.0 + (sV * Math.Cos(hV) / Math.Cos(Math.PI / 3 - hV))));
b = (double)(iV * (1.0 - sV));
g = (double)(3.0 * iV - r - b);
}
else if (hV >= 2 * Math.PI / 3 && hV < 4 * Math.PI / 3)
{
g = (double)(iV * (1.0 + sV * Math.Cos(hV - 2 * Math.PI / 3) / Math.Cos(Math.PI - hV)));
r = (double)(iV * (1.0 - sV));
b = (double)(3.0 * iV - r - g);
}
else
{
g = (double)(iV * (1.0 - sV));
b = (double)(iV * (1.0 + sV * Math.Cos(hV - 4 * Math.PI / 3) / Math.Cos(5 * Math.PI / 3 - hV)));
r = (double)(3.0 * iV - g - b);
}
rgbValue[x * 3 + y * w * 3] = (byte)(Math.Min(255, b * 255.0));
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(Math.Min(255, g * 255.0));
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(Math.Min(255, r * 255.0));
}
}
return rgbValue;
}
else
{
return null;
}
}



        /// <summary>
/// Get YIQ information.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] YIQValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] yiqValue = new double[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = temp[x * 4 + y * w * 4];
g = temp[x * 4 + 1 + y * w * 4];
r = temp[x * 4 + 2 + y * w * 4];
yiqValue[x * 3 + y * w * 3] = (double)(0.299 * (double)r + 0.587 * (double)g + 0.114 * (double)b);
yiqValue[x * 3 + 1 + y * w * 3] = (double)(0.596 * (double)r - 0.275 * (double)g - 0.321 * (double)b);
yiqValue[x * 3 + 2 + y * w * 3] = (double)(0.212 * (double)r - 0.523 * (double)g + 0.311 * (double)b);
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return yiqValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert rgb to yiq.
/// </summary>
/// <param name="rgbValue">The rgb information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoYIQ(byte[] rgbValue, int w, int h)
{
if (rgbValue != null)
{
double[] yiqValue = new double[w * h * 3];
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = rgbValue[x * 3 + y * w * 3];
g = rgbValue[x * 3 + 1 + y * w * 3];
r = rgbValue[x * 3 + 2 + y * w * 3];
yiqValue[x * 3 + y * w * 3] = (double)(0.299 * (double)r + 0.587 * (double)g + 0.114 * (double)b);
yiqValue[x * 3 + 1 + y * w * 3] = (double)(0.596 * (double)r - 0.275 * (double)g - 0.321 * (double)b);
yiqValue[x * 3 + 2 + y * w * 3] = (double)(0.212 * (double)r - 0.523 * (double)g + 0.311 * (double)b);
}
}
return yiqValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert yiq to rgb.
/// </summary>
/// <param name="yiqValue">The yiq information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] YIQtoRGB(byte[] yiqValue, int w, int h)
{
if (yiqValue != null)
{
double[] rgbValue = new double[w * h * 3];
double yV = 0, iV = 0, qV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
yV = yiqValue[x * 3 + y * w * 3];
iV = yiqValue[x * 3 + 1 + y * w * 3];
qV = yiqValue[x * 3 + 2 + y * w * 3];
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(1 * yV + 0.9560 * iV + 0.6210 * qV);
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(1 * yV - 0.2720 * iV - 0.6470 * qV);
rgbValue[x * 3 + y * w * 3] = (byte)(1 * yV - 1.1070 * iV + 1.7040 * qV);
}
}
return rgbValue;
}
else
{
return null;
}
}

4.6 HSV颜色空间

[空间解析]

  HSV彩色空间是一种适合肉眼分辨的模型。
  H—色相,表示色彩信息,即所处的光谱颜色的位置。该参数用角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。
  S—饱和度,该参数为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。
  V—亮度,表示色彩的明亮程度,范围从0到1。

  HSV颜色空间模型如下图所示:

        /// <summary>
/// Get HSV information.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] HSVValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] hsvValue = new double[w * h * 3];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
double r = 0, g = 0, b = 0;
double min = 0, max = 0;
double hV = 0, sV = 0, vV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = (double)temp[x * 4 + y * w * 4]/255.0;
g = (double)temp[x * 4 + 1 + y * w * 4]/255.0;
r = (double)temp[x * 4 + 2 + y * w * 4]/255.0;
min = Math.Min(r, Math.Min(g, b));
max = Math.Max(r, Math.Max(g, b));
if (max == min)
hV = 0;
if (max == r && g >= b)
hV = 60.0 * (g - b) / (max - min);
if (max == r && g < b)
hV = 60.0 * (g - b) / (max - min) + 360.0;
if (max == g)
hV = 60.0 * (b - r) / (max - min) + 120.0;
if (max == b)
hV = 60.0 * (r - g) / (max - min) + 240.0;
if (max == 0)
sV = 0;
else
sV = (max - min) / max;
vV = max;
hsvValue[x * 3 + y * w * 3] = (double)(hV);
hsvValue[x * 3 + 1 + y * w * 3] = (double)(sV);
hsvValue[x * 3 + 2 + y * w * 3] = (double)(vV);
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return hsvValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert rgb to hsv.
/// </summary>
/// <param name="rgbValue">The rgb information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoHSV(byte[] rgbValue, int w, int h)
{
if (rgbValue != null)
{
double[] hsvValue = new double[w * h * 3];
double r = 0, g = 0, b = 0;
double min = 0, max = 0;
double hV = 0, sV = 0, vV = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
r = (double)rgbValue[x * 3 + 2 + y * w * 3] / 255.0;
g = (double)rgbValue[x * 3 + 1 + y * w * 3] / 255.0;
b = (double)rgbValue[x * 3 + y * w * 3] / 255.0;
min = Math.Min(r, Math.Min(g, b));
max = Math.Max(r, Math.Max(g, b));
if (max == min)
hV = 0;
if (max == r && g >= b)
hV = 60.0 * (g - b) / (max - min);
if (max == r && g < b)
hV = 60.0 * (g - b) / (max - min) + 360.0;
if (max == g)
hV = 60.0 * (b - r) / (max - min) + 120.0;
if (max == b)
hV = 60.0 * (r - g) / (max - min) + 240.0;
if (max == 0)
sV = 0;
else
sV = (max - min) / max;
vV = max;
hsvValue[x * 3 + y * w * 3] = (double)(hV);
hsvValue[x * 3 + 1 + y * w * 3] = (double)(sV);
hsvValue[x * 3 + 2 + y * w * 3] = (double)(vV);
}
}
return hsvValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert hsv to rgb.
/// </summary>
/// <param name="hsvValue">The hsv information.</param>
/// <param name="w">The width of souce image.</param>
/// <param name="h">The height of souce image.</param>
/// <returns></returns>
public static double[] HSVtoRGB(byte[] hsvValue, int w, int h)
{
if (hsvValue != null)
{
double[] rgbValue = new double[w * h * 3];
double hV = 0, sV = 0, vV = 0, r = 0, g = 0, b = 0, p = 0, q = 0, t = 0;
int hN = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
hV = hsvValue[x * 3 + y * w * 3];
sV = hsvValue[x * 3 + 1 + y * w * 3];
vV = hsvValue[x * 3 + 2 + y * w * 3];
if (hV < 0)
hV = 360 + hV;
hN = (int)(hV / 60);
p = vV * (1.0 - sV);
q = vV * (1.0 - (hV / 60.0 - hN) * sV);
t = vV * (1.0 - (1.0 - (hV / 60.0 - hN)) * sV);
switch (hN)
{
case 0:
r = vV;
g = t;
b = p;
break;
case 1:
r = q;
g = vV;
b = p;
break;
case 2:
r = p;
g = vV;
b = t;
break;
case 3:
r = p;
g = q;
b = vV;
break;
case 4:
r = t;
g = p;
b = vV;
break;
case 5:
r = vV;
g = p;
b = q;
break;
default:
break;
}
rgbValue[x * 3 + y * w * 3] = (byte)(255.0 * b);
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(255.0 * g);
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(255.0 * r);
}
}
return rgbValue;
}
else
{
return null;
}
}

        /// <summary>
/// Get cmyk information.
/// </summary>
/// <param name="src">The source image.</param>
/// <returns></returns>
public static double[] CMYKValue(WriteableBitmap src)
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
double[] cmykValue = new double[w * h * 4];
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] temp = src.PixelBuffer.ToArray();
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = temp[x * 4 + y * w * 4];
g = temp[x * 4 + 1 + y * w * 4];
r = temp[x * 4 + 2 + y * w * 4];
cmykValue[x * 4 + y * w * 4] = (double)(g + b);
cmykValue[x * 4 + 1 + y * w * 4] = (double)(r + b);
cmykValue[x * 4 + 2 + y * w * 4] = (double)(r + g);
cmykValue[x * 4 + 3 + y * w * 4] = (double)(Math.Min((g + b), Math.Min((r + b), (r + g))));
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(temp, 0, w * 4 * h);
return cmykValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert rgb to cmyk.
/// </summary>
/// <param name="rgbValue">The rgb information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] RGBtoCMYK(byte[] rgbValue, int w, int h)
{
if (rgbValue != null)
{
double[] cmykValue = new double[w * h * 4];
int r = 0, g = 0, b = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
b = rgbValue[x * 3 + y * w * 3];
g = rgbValue[x * 3 + 1 + y * w * 3];
r = rgbValue[x * 3 + 2 + y * w * 3];
cmykValue[x * 4 + y * w * 4] = (double)(g + b);
cmykValue[x * 4 + 1 + y * w * 4] = (double)(r + b);
cmykValue[x * 4 + 2 + y * w * 4] = (double)(r + g);
cmykValue[x * 4 + 3 + y * w * 4] = (double)(Math.Min((g + b), Math.Min((r + b), (r + g))));
}
}
return cmykValue;
}
else
{
return null;
}
}
/// <summary>
/// Convert cmyk to rgb.
/// </summary>
/// <param name="cmykValue">The cmyk information.</param>
/// <param name="w">The width of source image.</param>
/// <param name="h">The height of source image.</param>
/// <returns></returns>
public static double[] CMYKtoRGB(byte[] cmykValue, int w, int h)
{
if (cmykValue != null)
{
double[] rgbValue = new double[w * h * 3];
double cV = 0, mV = 0, yV = 0,kV=0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
cV = cmykValue[x * 4 + y * w * 3];
mV = cmykValue[x * 4 + 1 + y * w * 3];
yV = cmykValue[x * 4 + 2 + y * w * 3];
kV = cmykValue[x * 4 + 3 + y * w * 3];
rgbValue[x * 3 + y * w * 3] = (byte)(0.5 * (mV + cV - yV));
rgbValue[x * 3 + 1 + y * w * 3] = (byte)(0.5 * (yV + cV - mV));
rgbValue[x * 3 + 2 + y * w * 3] = (byte)(0.5 * (mV + yV - cV));
}
}
return rgbValue;
}
else
{
return null;
}
}

最后,分享一个专业的图像处理网站(微像素),里面有很多源代码下载:

Win8 Metro(C#)数字图像处理--4图像颜色空间描述的更多相关文章

  1. Win8 Metro(C#) 数字图像处理--1 图像打开,保存

    原文:Win8 Metro(C#) 数字图像处理--1 图像打开,保存 作为本专栏的第一篇,必不可少的需要介绍一下图像的打开与保存,一便大家后面DEMO的制作.   Win8Metro编程中,图像相关 ...

  2. Win8 Metro(C#)数字图像处理--3.2图像方差计算

    原文:Win8 Metro(C#)数字图像处理--3.2图像方差计算 /// <summary> /// /// </summary>Variance computing. / ...

  3. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary> /// Get the array of histrgram. /// </sum ...

  4. Win8 Metro(C#)数字图像处理--3.4图像信息熵计算

    原文:Win8 Metro(C#)数字图像处理--3.4图像信息熵计算 [函数代码] /// <summary> /// Entropy of one image. /// </su ...

  5. Win8 Metro(C#)数字图像处理--3.5图像形心计算

    原文:Win8 Metro(C#)数字图像处理--3.5图像形心计算 /// <summary> /// Get the center of the object in an image. ...

  6. Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效

    原文:Win8 Metro(C#)数字图像处理--2.73一种背景图像融合特效 /// <summary> /// Image merge process. /// </summar ...

  7. Win8 Metro(C#)数字图像处理--3.1图像均值计算

    原文:Win8 Metro(C#)数字图像处理--3.1图像均值计算 /// <summary> /// Mean value computing. /// </summary> ...

  8. Win8 Metro(C#)数字图像处理--2.74图像凸包计算

    原文:Win8 Metro(C#)数字图像处理--2.74图像凸包计算 /// <summary> /// Convex Hull compute. /// </summary> ...

  9. Win8 Metro(C#)数字图像处理--2.68图像最小值滤波器

    原文:Win8 Metro(C#)数字图像处理--2.68图像最小值滤波器 /// <summary> /// Min value filter. /// </summary> ...

随机推荐

  1. JS中的JSON对象 定义和取值

    1.JSON(JavaScript Object Notation)一种简单的数据格式,比xml更轻巧.JSON是JavaScript原生格式,这意味着在JavaScript中处理JSON数据不需要任 ...

  2. html5-1 网页结构描述

    html5-1 网页结构描述 一.总结 一句话总结:注意head中的title,keywords,description,这对seo优化很有帮助 1.如何给某元素动态使用类似onclick方法? 点o ...

  3. 小强的HTML5移动开发之路(31)—— JavaScript回顾6

    HTML DOM模型: w3c dom 模型(规范)出现之前,各个浏览器自己支持的一些dom操作 Select对象 属性: selectedIndex:表示用户现在选择的那个选项的下标(从0开始) l ...

  4. 【基础练习】【线性DP】codevs1576 最长严格上升子序列题解

    连题目都不放了,就是标题中说的那样.裸题 于是直接上代码 暑假要来了 好好学习 --炉火照天地,红星乱紫烟. 赧郎明月夜.歌曲动寒川.

  5. Android Activity 悬浮 半透明边框

    1.首先来创建一个Activity,在Activity的OnCreate函数里面我们设置它为全屏,然后设置Activity的宽高为全屏*0.9,然后设置背景图片为半透明的 .9 图片 .这样就已经是非 ...

  6. 调试分析工具 (C/C++)

    一.静态分析工具 cppcheck cppcheck主要用于对C/C++源代码进行分析检查的一个开源工具,可以用来检测未使用的变量.越界访问.内存泄漏等问题. 使用方法 cppcheck --enab ...

  7. C# 静态构造函数,静态变量执行顺序(升华版)

    上篇 是基本语法基础下的执行顺序,包括继承这个维度下的执行顺序,我们可以依照的规律顺下来,下面我们看下一些摸不到头脑的情况 我们实验 一个 类中的方法 去调用另一个非继承类的情况,  我们主要看下  ...

  8. 《Java并发编程实战》第十二章 测试并发程序 读书笔记

    并发测试分为两类:安全性测试(无论错误的行为不会发生)而活性测试(会发生). 安全測试 - 通常採用測试不变性条件的形式,即推断某个类的行为是否与其它规范保持一致. 活跃性測试 - 包含进展測试和无进 ...

  9. NAT对于网络上的其它人都不可见(但可以转发端口),Bridged和网络里的其它物理机没区别,Internal只能在虚拟机之间可见,Host-only只对主机可见(最符合我的服务器需求),最多可设置8块网卡实现混杂

    VirtualBox 可以为每一个虚拟机分配8个网卡.每一个网卡的连接方式可以选为下列之一: Not attached Network Address Translation (NAT) Bridge ...

  10. GDI+与WPF中的颜色简析

    原文:GDI+与WPF中的颜色简析 --------------------------------------------------------------------------------引用 ...