/// <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> /// /// <returns>Returns <see cref="YCbCr"/> instance, which represents converted color value.</returns> /// public static YCbCr FromRGB(RGB rgb) { YCbCr ycbcr = new YCbCr( ); FromRGB(rgb, ycbcr); return(ycbcr); }
/// <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 FromRGB(RGB rgb, YCbCr ycbcr) { float r = (float)rgb.Red / 255; float g = (float)rgb.Green / 255; float b = (float)rgb.Blue / 255; ycbcr.Y = (float)(0.2989 * r + 0.5866 * g + 0.1145 * b); ycbcr.Cb = (float)(-0.1687 * r - 0.3313 * g + 0.5000 * b); ycbcr.Cr = (float)(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 ToRGB(YCbCr ycbcr, RGB rgb) { // don't warry about zeros. compiler will remove them float r = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y + 0.0000 * ycbcr.Cb + 1.4022 * ycbcr.Cr))); float g = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y - 0.3456 * ycbcr.Cb - 0.7145 * ycbcr.Cr))); float b = Math.Max(0.0f, Math.Min(1.0f, (float)(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); rgb.Alpha = 255; }
// Gather statistics for the specified image private unsafe void ProcessImage(UnmanagedImage image, byte *mask, int maskLineSize) { // get image dimension int width = image.Width; int height = image.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 pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4; int offset = image.Stride - width * pixelSize; int maskOffset = maskLineSize - width; // do the job byte *p = (byte *)image.ImageData.ToPointer( ); if (mask == null) { // for each line for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, p += pixelSize) { rgb.Red = p[RGB.R]; rgb.Green = p[RGB.G]; rgb.Blue = p[RGB.B]; // convert to YCbCr color space AForgeCore.Imaging.YCbCr.FromRGB(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; } } else { // for each line for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, p += pixelSize, mask++) { if (*mask == 0) { continue; } rgb.Red = p[RGB.R]; rgb.Green = p[RGB.G]; rgb.Blue = p[RGB.B]; // convert to YCbCr color space AForgeCore.Imaging.YCbCr.FromRGB(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; mask += maskOffset; } } // create histograms yHistogram = new ContinuousHistogram(yhisto, new Range(0.0f, 1.0f)); cbHistogram = new ContinuousHistogram(cbhisto, new Range(-0.5f, 0.5f)); crHistogram = new ContinuousHistogram(crhisto, new Range(-0.5f, 0.5f)); yHistogramWithoutBlack = new ContinuousHistogram(yhistoWB, new Range(0.0f, 1.0f)); cbHistogramWithoutBlack = new ContinuousHistogram(cbhistoWB, new Range(-0.5f, 0.5f)); crHistogramWithoutBlack = new ContinuousHistogram(crhistoWB, new Range(-0.5f, 0.5f)); }