图像颜色空间是图像颜色集合的数学表示,本小节将针对几种常见颜色空间做个简单介绍。
/// <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;
}
}
最后,分享一个专业的图像处理网站(微像素),里面有很多源代码下载: http://www.zealpixel.com/portal.php