/// <summary> /// Convert from RGB to YCbCr color space (Rec 601-1 specification) /// </summary> /// /// <param name="rgb">Source color in <b>RGB</b> color space</param> /// <param name="ycbcr">Destination color in <b>YCbCr</b> color space</param> /// public static void RGB2YCbCr(RGB rgb, YCbCr ycbcr) { double r = (double)rgb.Red / 255; double g = (double)rgb.Green / 255; double b = (double)rgb.Blue / 255; ycbcr.Y = 0.2989 * r + 0.5866 * g + 0.1145 * b; ycbcr.Cb = -0.1687 * r - 0.3313 * g + 0.5000 * b; ycbcr.Cr = 0.5000 * r - 0.4184 * g - 0.0816 * b; }
/// <summary> /// Convert from YCbCr to RGB color space /// </summary> /// /// <param name="ycbcr">Source color in <b>YCbCr</b> color space</param> /// <param name="rgb">Destination color in <b>RGB</b> color spacs</param> /// public static void YCbCr2RGB(YCbCr ycbcr, RGB rgb) { // don't warry about zeros. compiler will remove them double r = Math.Max(0.0, Math.Min(1.0, ycbcr.Y + 0.0000 * ycbcr.Cb + 1.4022 * ycbcr.Cr)); double g = Math.Max(0.0, Math.Min(1.0, ycbcr.Y - 0.3456 * ycbcr.Cb - 0.7145 * ycbcr.Cr)); double b = Math.Max(0.0, Math.Min(1.0, ycbcr.Y + 1.7710 * ycbcr.Cb + 0.0000 * ycbcr.Cr)); rgb.Red = (byte)(r * 255); rgb.Green = (byte)(g * 255); rgb.Blue = (byte)(b * 255); }
/// <summary> /// Gather statistics about specified image /// </summary> /// /// <param name="imageData">Image data</param> /// private void ProcessImage(BitmapData imageData) { // get image dimension int width = imageData.Width; int height = imageData.Height; pixels = pixelsWithoutBlack = 0; int[] yhisto = new int[256]; int[] cbhisto = new int[256]; int[] crhisto = new int[256]; int[] yhistoWB = new int[256]; int[] cbhistoWB = new int[256]; int[] crhistoWB = new int[256]; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); int offset = imageData.Stride - width * 3; // do the job unsafe { byte *p = (byte *)imageData.Scan0.ToPointer( ); // for each line for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, p += 3) { rgb.Red = p[RGB.R]; rgb.Green = p[RGB.G]; rgb.Blue = p[RGB.B]; // convert to YCbCr color space BaseControls.ImageBox.Imaging.ColorConverter.RGB2YCbCr(rgb, ycbcr); yhisto [(int)(ycbcr.Y * 255)]++; cbhisto[(int)((ycbcr.Cb + 0.5) * 255)]++; crhisto[(int)((ycbcr.Cr + 0.5) * 255)]++; pixels++; if ((ycbcr.Y != 0.0) || (ycbcr.Cb != 0.0) || (ycbcr.Cr != 0.0)) { yhistoWB [(int)(ycbcr.Y * 255)]++; cbhistoWB[(int)((ycbcr.Cb + 0.5) * 255)]++; crhistoWB[(int)((ycbcr.Cr + 0.5) * 255)]++; pixelsWithoutBlack++; } } p += offset; } } // create histograms yHistogram = new ContinuousHistogram(yhisto, new DoubleRange(0.0, 1.0)); cbHistogram = new ContinuousHistogram(cbhisto, new DoubleRange(-0.5, 0.5)); crHistogram = new ContinuousHistogram(crhisto, new DoubleRange(-0.5, 0.5)); yHistogramWithoutBlack = new ContinuousHistogram(yhistoWB, new DoubleRange(0.0, 1.0)); cbHistogramWithoutBlack = new ContinuousHistogram(cbhistoWB, new DoubleRange(-0.5, 0.5)); crHistogramWithoutBlack = new ContinuousHistogram(crhistoWB, new DoubleRange(-0.5, 0.5)); }