图像颜色空间是图像颜色集合的数学表示,本小节将针对几种常见颜色空间做个简单介绍。
/// <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; } }