private void CreateYCbCrLayout() { Hide4Elements(); label1.Text = "Y"; label2.Text = "Cb"; label3.Text = "Cr"; YCbCr YCbCrColor = new YCbCr(current_color); setting_tb_and_nup = true; numericUpDown1.Maximum = 1; numericUpDown2.Maximum = 1; numericUpDown3.Maximum = 1; numericUpDown1.Minimum = 0; numericUpDown2.Minimum = 0; numericUpDown3.Minimum = 0; numericUpDown1.Increment = new decimal(0.01); numericUpDown2.Increment = new decimal(0.01); numericUpDown3.Increment = new decimal(0.01); trackBar1.Value = (int)(255 * YCbCrColor.Y); trackBar2.Value = (int)(255 * YCbCrColor.Cb); trackBar3.Value = (int)(255 * YCbCrColor.Cr); numericUpDown1.Value = (decimal)YCbCrColor.Y; numericUpDown2.Value = (decimal)YCbCrColor.Cb; numericUpDown3.Value = (decimal)YCbCrColor.Cr; setting_tb_and_nup = false; SetDecimalPlaces(3); SetYCbCrLabels(); }
public ColorClose(Pixel key, int tola, int tolb) { _key = key.YCbCr(); _tola = tola; _tolb = tolb; _tolba = _tolb - _tola; }
public void Convert_YCbCr_to_CieXyz(float y2, float cb, float cr, float x, float y, float z) { // Arrange var input = new YCbCr(y2, cb, cr); var expected = new CieXyz(x, y, z); Span <YCbCr> inputSpan = new YCbCr[5]; inputSpan.Fill(input); Span <CieXyz> actualSpan = new CieXyz[5]; // Act var actual = Converter.ToCieXyz(input); Converter.Convert(inputSpan, actualSpan, actualSpan.Length); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_CieLab_to_YCbCr(float l, float a, float b, float y, float cb, float cr) { // Arrange var input = new CieLab(l, a, b); var expected = new YCbCr(y, cb, cr); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <YCbCr> actualSpan = new YCbCr[5]; // Act var actual = Converter.ToYCbCr(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_Rgb_To_YCbCr(float r, float g, float b, float y, float cb, float cr) { // Arrange var input = new Rgb(r, g, b); var expected = new YCbCr(y, cb, cr); Span <Rgb> inputSpan = new Rgb[5]; inputSpan.Fill(input); Span <YCbCr> actualSpan = new YCbCr[5]; // Act var actual = Converter.ToYCbCr(input); Converter.Convert(inputSpan, actualSpan, actualSpan.Length); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_Cmyk_to_YCbCr(float c, float m, float y, float k, float y2, float cb, float cr) { // Arrange var input = new Cmyk(c, m, y, k); var expected = new YCbCr(y2, cb, cr); Span <Cmyk> inputSpan = new Cmyk[5]; inputSpan.Fill(input); Span <YCbCr> actualSpan = new YCbCr[5]; // Act var actual = Converter.ToYCbCr(input); Converter.Convert(inputSpan, actualSpan, actualSpan.Length); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
/// <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> /// Apply filter. /// </summary> /// <param name="bmData">Bitmap</param> public unsafe void Apply(BitmapData bmData) { byte *p = (byte *)bmData.Scan0.ToPointer(); int width = bmData.Width, height = bmData.Height, stride = bmData.Stride; Parallel.For(0, height, j => { YCbCr ycbcr; RGB rgb; int i, k, jstride = j * stride; for (i = 0; i < width; i++) { k = jstride + i * 4; ycbcr = YCbCr.FromRGB(p[k + 2], p[k + 1], p[k + 0]); ycbcr.Y += y; ycbcr.Cb += cb; ycbcr.Cr += cr; rgb = ycbcr.ToRGB; p[k + 0] = rgb.Blue; p[k + 1] = rgb.Green; p[k + 2] = rgb.Red; } } ); return; }
public void Convert_YCbCr_to_CieLuv(float y, float cb, float cr, float l, float u, float v) { // Arrange var input = new YCbCr(y, cb, cr); var expected = new CieLuv(l, u, v); Span <YCbCr> inputSpan = new YCbCr[5]; inputSpan.Fill(input); Span <CieLuv> actualSpan = new CieLuv[5]; // Act var actual = Converter.ToCieLuv(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="LinearRgb"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="LinearRgb"/></returns> public LinearRgb ToLinearRgb(YCbCr color) { Guard.NotNull(color, nameof(color)); var rgb = this.ToRgb(color); return(this.ToLinearRgb(rgb)); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="Cmyk"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Cmyk"/></returns> public Cmyk ToCmyk(YCbCr color) { Guard.NotNull(color, nameof(color)); var rgb = this.ToRgb(color); return(CmykAndRgbConverter.Convert(rgb)); }
public static RGB YCbCrToRGB(YCbCr ycbcr) { var r = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y + 0.0000 * ycbcr.Cb + 1.4022 * ycbcr.Cr))); var g = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y - 0.3456 * ycbcr.Cb - 0.7145 * ycbcr.Cr))); var b = Math.Max(0.0f, Math.Min(1.0f, (float)(ycbcr.Y + 1.7710 * ycbcr.Cb + 0.0000 * ycbcr.Cr))); return(new RGB((byte)(r * 255), (byte)(g * 255), (byte)(b * 255))); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="Lms"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Lms"/></returns> public Lms ToLms(YCbCr color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToLms(xyzColor)); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="HunterLab"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="HunterLab"/></returns> public HunterLab ToHunterLab(YCbCr color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToHunterLab(xyzColor)); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="Rgb"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Rgb"/></returns> public Rgb ToRgb(YCbCr color) { // Conversion Rgb rgb = YCbCrAndRgbConverter.Convert(color); // Adaptation return(this.Adapt(rgb)); }
private void SetYCbCrLabels() { YCbCr yCbCrColor = new YCbCr(current_color); label_YCbCr_Y.Text = "Y: " + yCbCrColor.Y.ToString("0.000"); label_YCbCr_Cb.Text = "Cb: " + yCbCrColor.Cb.ToString("0.000"); label_YCbCr_Cr.Text = "Cr: " + yCbCrColor.Cr.ToString("0.000"); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="Hsl"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Hsl"/></returns> public Hsl ToHsl(YCbCr color) { Guard.NotNull(color, nameof(color)); var rgb = this.ToRgb(color); return(HslAndRgbConverter.Convert(rgb)); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="CieLchuv"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieLchuv"/></returns> public CieLchuv ToCieLchuv(YCbCr color) { Guard.NotNull(color, nameof(color)); CieXyz xyzColor = this.ToCieXyz(color); return(this.ToCieLchuv(xyzColor)); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="CieXyz"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieXyz"/></returns> public CieXyz ToCieXyz(YCbCr color) { Guard.NotNull(color, nameof(color)); // Conversion var rgb = this.ToRgb(color); return(this.ToCieXyz(rgb)); }
void IDCT() { //YCbCrBlockCollection = new YCbCrBlock[blockCount.x, blockCount.y]; for (int i = 0; i < enc.BlockCount.x; i++) { for (int j = 0; j < enc.BlockCount.y; j++) { enc.YCbCrBlockCollection[i, j].Block = CreateYCbCrBlock(enc.FDCTBlockCollection[i, j].Block); } } YCbCr[,] CreateYCbCrBlock(FDCTValue[,] block) { var yCbCrBlock = new YCbCr[enc.Blocksize, enc.Blocksize]; //8x8 block von dct werten for (int x = 0; x < enc.Blocksize; x++) { for (int y = 0; y < enc.Blocksize; y++) { //einzelnen dct wert double sum_y = 0; double sum_cb = 0; double sum_cr = 0; for (int u = 0; u < 8; u++) { for (int v = 0; v < 8; v++) { double cu = u == 0 ? 1 / Math.Sqrt(2) : 1; double cv = v == 0 ? 1 / Math.Sqrt(2) : 1; double cos1 = Math.Cos((2 * x + 1) * (u * Math.PI) / 16); double cos2 = Math.Cos((2 * y + 1) * (v * Math.PI) / 16); sum_y += cu * cv * block[u, v].Y_FDCT * cos1 * cos2; sum_cb += cu * cv * block[u, v].Cb_FDCT * cos1 * cos2; sum_cr += cu * cv * block[u, v].Cr_FDCT * cos1 * cos2; } } //einzelner ycbcr wert (Syx) double Sxy_Y = 0.25 * sum_y; double Sxy_Cb = 0.25 * sum_cb; double Sxy_Cr = 0.25 * sum_cr; yCbCrBlock[x, y].Y = Sxy_Y; yCbCrBlock[x, y].Cb = Sxy_Cb; yCbCrBlock[x, y].Cr = Sxy_Cr; } } return(yCbCrBlock); } }
/// <summary> /// Converts from their colorspace to RGB and combines all previously decoded channels /// </summary> /// <param name="imgInfo"></param> /// <param name="imgS"></param> /// <returns>A 2D array representing the color data from the image</returns> internal static Color2[,] MergeChannels(ImgInfo imgInfo, float[][,] imgS) { var img = new Color2[imgInfo.height, imgInfo.width]; IColorspaceConverter converter; if (imgInfo.app14MarkerFound) { switch (imgInfo.colorMode) { case Markers.App14ColorMode.Unknown: converter = imgInfo.numOfComponents == 3 ? new Rgb() : (IColorspaceConverter) new YCbCr(); break; case Markers.App14ColorMode.YCbCr: converter = new YCbCr(); break; case Markers.App14ColorMode.YCCK: converter = new YCbCr(); break; default: converter = new Rgb(); break; } } else { converter = new YCbCr(); } for (int y = 0; y < imgInfo.height; y++) { for (int x = 0; x < imgInfo.width; x++) { Info info; if (imgInfo.numOfComponents == 1) // Y { info.a = imgS[0][y, x]; info.b = 0; info.c = 0; } else // YCbCr { info.a = imgS[0][y, x]; info.b = imgS[1][y, x]; info.c = imgS[2][y, x]; } img[y, x] = converter.ConvertToRgb(info); } } return(img); }
/// <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> /// Converts a <see cref="YCbCr"/> into a <see cref="Rgb"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Rgb"/></returns> public Rgb ToRgb(YCbCr color) { Guard.NotNull(color, nameof(color)); // Conversion Rgb rgb = YCbCrAndRgbConverter.Convert(color); // Adaptation return(this.Adapt(rgb)); }
/// <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 YCbCr FromRGB(Color rgb, YCbCr ycbcr) { float r = (float)rgb.R / 255; float g = (float)rgb.G / 255; float b = (float)rgb.B / 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); return(ycbcr); }
/// <summary> /// Converts a <see cref="YCbCr"/> into a <see cref="Rgb"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Rgb"/></returns> public Rgb ToRgb(YCbCr color) { Guard.NotNull(color, nameof(color)); // Conversion Rgb rgb = YCbCrAndRgbConverter.Convert(color); // Adaptation // TODO: Check this! return(rgb.WorkingSpace.Equals(this.TargetRgbWorkingSpace) ? rgb : this.Adapt(rgb)); }
public void YCbCrConstructorAssignsFields() { const float y = 75F; const float cb = 64F; const float cr = 87F; var yCbCr = new YCbCr(y, cb, cr); Assert.Equal(y, yCbCr.Y); Assert.Equal(cb, yCbCr.Cb); Assert.Equal(cr, yCbCr.Cr); }
/// <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 = System.Math.Max(0.0f, System.Math.Min(1.0f, (float)(ycbcr.Y + 0.0000 * ycbcr.Cb + 1.4022 * ycbcr.Cr))); float g = System.Math.Max(0.0f, System.Math.Min(1.0f, (float)(ycbcr.Y - 0.3456 * ycbcr.Cb - 0.7145 * ycbcr.Cr))); float b = System.Math.Max(0.0f, System.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; }
private static X YCbCrToX_JPEG <X>(YCbCr ycbcr, Func <double, double, double, X> func) { double Y = ycbcr.Y; double Cr = ycbcr.Cr; double Cb = ycbcr.Cb; double R = Y + 1.40200 * (Cr - 128); double G = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128); double B = Y + 1.77200 * (Cb - 128); return(func(R, G, B)); }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// <param name="destinationData">Destination image data.</param> /// protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) { int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; // get width and height int width = sourceData.Width; int height = sourceData.Height; int srcOffset = sourceData.Stride - width * pixelSize; int dstOffset = destinationData.Stride - width; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); // do the job byte *src = (byte *)sourceData.ImageData.ToPointer( ); byte *dst = (byte *)destinationData.ImageData.ToPointer( ); byte v = 0; // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst++) { rgb.Red = src[RGB.R]; rgb.Green = src[RGB.G]; rgb.Blue = src[RGB.B]; // convert to YCbCr AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); switch (channel) { case YCbCr.YIndex: v = (byte)(ycbcr.Y * 255); break; case YCbCr.CbIndex: v = (byte)((ycbcr.Cb + 0.5) * 255); break; case YCbCr.CrIndex: v = (byte)((ycbcr.Cr + 0.5) * 255); break; } *dst = v; } src += srcOffset; dst += dstOffset; } }
public void Convert_Rgb_To_YCbCr(float r, float g, float b, float y, float cb, float cr) { // Arrange var input = new Rgb(r, g, b); // Act YCbCr output = Converter.ToYCbCr(input); // Assert Assert.Equal(y, output.Y, FloatRoundingComparer); Assert.Equal(cb, output.Cb, FloatRoundingComparer); Assert.Equal(cr, output.Cr, FloatRoundingComparer); }
/// <summary> /// For high definition TV (HDTV) /// </summary> /// <typeparam name="X"></typeparam> /// <param name="ycbcr"></param> /// <param name="func"></param> /// <returns></returns> private static X YCbCrToX_BT709 <X>(YCbCr ycbcr, Func <double, double, double, X> func) { double Y = ycbcr.Y; double Cr = ycbcr.Cr; double Cb = ycbcr.Cb; // http://www.equasys.de/colorconversion.html double R = 1.164 * (Y - 16) + 1.596 * (Cr - 128); double G = 1.164 * (Y - 16) - 0.392 * (Cb - 128) - 0.813 * (Cr - 128); double B = 1.164 * (Y - 16) + 2.017 * (Cb - 128); return(func(R, G, B)); }
// Process the filter private unsafe void ProcessFilter( BitmapData data ) { int width = data.Width; int height = data.Height; // lock overlay image BitmapData ovrData = channelImage.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed ); int offset = data.Stride - width * 3; int offsetOvr = ovrData.Stride - width; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); // do the job unsafe { byte * dst = (byte *) data.Scan0.ToPointer( ); byte * ovr = (byte *) ovrData.Scan0.ToPointer( ); // for each line for ( int y = 0; y < height; y++ ) { // for each pixel for ( int x = 0; x < width; x++, dst += 3, ovr ++ ) { rgb.Red = dst[RGB.R]; rgb.Green = dst[RGB.G]; rgb.Blue = dst[RGB.B]; // convert to YCbCr AForge.Imaging.ColorConverter.RGB2YCbCr( rgb, ycbcr ); switch ( channel ) { case YCbCr.YIndex: ycbcr.Y = (double) *ovr / 255; break; case YCbCr.CbIndex: ycbcr.Cb = (double) *ovr / 255 - 0.5; break; case YCbCr.CrIndex: ycbcr.Cr = (double) *ovr / 255 - 0.5; break; } // convert back to RGB AForge.Imaging.ColorConverter.YCbCr2RGB( ycbcr, rgb ); dst[RGB.R] = rgb.Red; dst[RGB.G] = rgb.Green; dst[RGB.B] = rgb.Blue; } dst += offset; ovr += offsetOvr; } } // unlock channelImage.UnlockBits( ovrData ); }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// <param name="rect">Image rectangle for processing by the filter.</param> /// protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) { int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; int startX = rect.Left; int startY = rect.Top; int stopX = startX + rect.Width; int stopY = startY + rect.Height; int offset = image.Stride - rect.Width * pixelSize; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); float ky = 0, by = 0; float kcb = 0, bcb = 0; float kcr = 0, bcr = 0; // Y line parameters if ( inY.Max != inY.Min ) { ky = ( outY.Max - outY.Min ) / ( inY.Max - inY.Min ); by = outY.Min - ky * inY.Min; } // Cb line parameters if ( inCb.Max != inCb.Min ) { kcb = ( outCb.Max - outCb.Min ) / ( inCb.Max - inCb.Min ); bcb = outCb.Min - kcb * inCb.Min; } // Cr line parameters if ( inCr.Max != inCr.Min ) { kcr = ( outCr.Max - outCr.Min ) / ( inCr.Max - inCr.Min ); bcr = outCr.Min - kcr * inCr.Min; } // do the job byte* ptr = (byte*) image.ImageData.ToPointer( ); // allign pointer to the first pixel to process ptr += ( startY * image.Stride + startX * pixelSize ); // for each row for ( int y = startY; y < stopY; y++ ) { // for each pixel for ( int x = startX; x < stopX; x++, ptr += pixelSize ) { rgb.Red = ptr[RGB.R]; rgb.Green = ptr[RGB.G]; rgb.Blue = ptr[RGB.B]; // convert to YCbCr BestCS.Imaging.YCbCr.FromRGB( rgb, ycbcr ); // correct Y if ( ycbcr.Y >= inY.Max ) ycbcr.Y = outY.Max; else if ( ycbcr.Y <= inY.Min ) ycbcr.Y = outY.Min; else ycbcr.Y = ky * ycbcr.Y + by; // correct Cb if ( ycbcr.Cb >= inCb.Max ) ycbcr.Cb = outCb.Max; else if ( ycbcr.Cb <= inCb.Min ) ycbcr.Cb = outCb.Min; else ycbcr.Cb = kcb * ycbcr.Cb + bcb; // correct Cr if ( ycbcr.Cr >= inCr.Max ) ycbcr.Cr = outCr.Max; else if ( ycbcr.Cr <= inCr.Min ) ycbcr.Cr = outCr.Min; else ycbcr.Cr = kcr * ycbcr.Cr + bcr; // convert back to RGB BestCS.Imaging.YCbCr.ToRGB( ycbcr, rgb ); ptr[RGB.R] = rgb.Red; ptr[RGB.G] = rgb.Green; ptr[RGB.B] = rgb.Blue; } ptr += offset; } }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// <param name="rect">Image rectangle for processing by the filter.</param> /// protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) { // get pixel size int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4; int startX = rect.Left; int startY = rect.Top; int stopX = startX + rect.Width; int stopY = startY + rect.Height; int offset = image.Stride - rect.Width * pixelSize; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); bool updated; // do the job byte* ptr = (byte*) image.ImageData.ToPointer( ); // allign pointer to the first pixel to process ptr += ( startY * image.Stride + startX * pixelSize ); // for each row for ( int y = startY; y < stopY; y++ ) { // for each pixel for ( int x = startX; x < stopX; x++, ptr += pixelSize ) { updated = false; rgb.Red = ptr[RGB.R]; rgb.Green = ptr[RGB.G]; rgb.Blue = ptr[RGB.B]; // convert to YCbCr AForge.Imaging.YCbCr.FromRGB( rgb, ycbcr ); // check YCbCr values if ( ( ycbcr.Y >= yRange.Min ) && ( ycbcr.Y <= yRange.Max ) && ( ycbcr.Cb >= cbRange.Min ) && ( ycbcr.Cb <= cbRange.Max ) && ( ycbcr.Cr >= crRange.Min ) && ( ycbcr.Cr <= crRange.Max ) ) { if ( !fillOutsideRange ) { if ( updateY ) ycbcr.Y = fillY; if ( updateCb ) ycbcr.Cb = fillCb; if ( updateCr ) ycbcr.Cr = fillCr; updated = true; } } else { if ( fillOutsideRange ) { if ( updateY ) ycbcr.Y = fillY; if ( updateCb ) ycbcr.Cb = fillCb; if ( updateCr ) ycbcr.Cr = fillCr; updated = true; } } if ( updated ) { // convert back to RGB AForge.Imaging.YCbCr.ToRGB( ycbcr, rgb ); ptr[RGB.R] = rgb.Red; ptr[RGB.G] = rgb.Green; ptr[RGB.B] = rgb.Blue; } } ptr += offset; } }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// <param name="destinationData">Destination image data.</param> /// protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData) { int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8; // get width and height int width = sourceData.Width; int height = sourceData.Height; int srcOffset = sourceData.Stride - width * pixelSize; int dstOffset = destinationData.Stride - width; RGB rgb = new RGB(); YCbCr ycbcr = new YCbCr(); // do the job byte* src = (byte*)sourceData.ImageData.ToPointer(); byte* dst = (byte*)destinationData.ImageData.ToPointer(); byte v = 0; // for each row for (int y = 0; y < height; y++) { // for each pixel for (int x = 0; x < width; x++, src += pixelSize, dst++) { rgb.Red = src[RGB.R]; rgb.Green = src[RGB.G]; rgb.Blue = src[RGB.B]; // convert to YCbCr AForge.Imaging.YCbCr.FromRGB(rgb, ycbcr); switch (channel) { case YCbCr.YIndex: v = (byte)(ycbcr.Y * 255); break; case YCbCr.CbIndex: v = (byte)((ycbcr.Cb + 0.5) * 255); break; case YCbCr.CrIndex: v = (byte)((ycbcr.Cr + 0.5) * 255); break; } *dst = v; } src += srcOffset; dst += dstOffset; } }
// Apply filter public Bitmap Apply( Bitmap srcImg ) { if ( srcImg.PixelFormat != PixelFormat.Format24bppRgb ) throw new ArgumentException( ); // get source image size int width = srcImg.Width; int height = srcImg.Height; // lock source bitmap data BitmapData srcData = srcImg.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb ); // create new grayscale image Bitmap dstImg = AForge.Imaging.Image.CreateGrayscaleImage( width, height ); // lock destination bitmap data BitmapData dstData = dstImg.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed ); int srcOffset = srcData.Stride - width * 3; int dstOffset = dstData.Stride - width; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); // do the job unsafe { byte * src = (byte *) srcData.Scan0.ToPointer( ); byte * dst = (byte *) dstData.Scan0.ToPointer( ); byte v = 0; // for each row for ( int y = 0; y < height; y++ ) { // for each pixel for ( int x = 0; x < width; x++, src += 3, dst ++ ) { rgb.Red = src[RGB.R]; rgb.Green = src[RGB.G]; rgb.Blue = src[RGB.B]; // convert to YCbCr AForge.Imaging.ColorConverter.RGB2YCbCr( rgb, ycbcr ); switch ( channel ) { case YCbCr.YIndex: v = (byte) ( ycbcr.Y * 255 ); break; case YCbCr.CbIndex: v = (byte) ( ( ycbcr.Cb + 0.5 ) * 255 ); break; case YCbCr.CrIndex: v = (byte) ( ( ycbcr.Cr + 0.5 ) * 255 ); break; } *dst = v; } src += srcOffset; dst += dstOffset; } } // unlock both images dstImg.UnlockBits( dstData ); srcImg.UnlockBits( srcData ); return dstImg; }
/// <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; }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// <param name="rect">Image rectangle for processing by the filter.</param> /// /// <exception cref="NullReferenceException">Channel image was not specified.</exception> /// <exception cref="InvalidImagePropertiesException">Channel image size does not match source /// image size.</exception> /// protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect ) { if ( ( channelImage == null ) && ( unmanagedChannelImage == null ) ) { throw new NullReferenceException( "Channel image was not specified." ); } int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8; int width = image.Width; int height = image.Height; int startX = rect.Left; int startY = rect.Top; int stopX = startX + rect.Width; int stopY = startY + rect.Height; int offset = image.Stride - rect.Width * pixelSize; BitmapData chData = null; // pointer to channel's data byte* ch; // channel's image stride int chStride = 0; // check channel's image type if ( channelImage != null ) { // check channel's image dimension if ( ( width != channelImage.Width ) || ( height != channelImage.Height ) ) throw new InvalidImagePropertiesException( "Channel image size does not match source image size." ); // lock channel image chData = channelImage.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed ); ch = (byte*) chData.Scan0.ToPointer( ); chStride = chData.Stride; } else { // check channel's image dimension if ( ( width != unmanagedChannelImage.Width ) || ( height != unmanagedChannelImage.Height ) ) throw new InvalidImagePropertiesException( "Channel image size does not match source image size." ); ch = (byte*) unmanagedChannelImage.ImageData; chStride = unmanagedChannelImage.Stride; } int offsetCh = chStride - rect.Width; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); // do the job byte* dst = (byte*) image.ImageData.ToPointer( ); // allign pointer to the first pixel to process dst += ( startY * image.Stride + startX * pixelSize ); ch += ( startY * chStride + startX ); // for each line for ( int y = startY; y < stopY; y++ ) { // for each pixel for ( int x = startX; x < stopX; x++, dst += pixelSize, ch++ ) { rgb.Red = dst[RGB.R]; rgb.Green = dst[RGB.G]; rgb.Blue = dst[RGB.B]; // convert to YCbCr AForge.Imaging.YCbCr.FromRGB( rgb, ycbcr ); switch ( channel ) { case YCbCr.YIndex: ycbcr.Y = (float) *ch / 255; break; case YCbCr.CbIndex: ycbcr.Cb = (float) *ch / 255 - 0.5f; break; case YCbCr.CrIndex: ycbcr.Cr = (float) *ch / 255 - 0.5f; break; } // convert back to RGB AForge.Imaging.YCbCr.ToRGB( ycbcr, rgb ); dst[RGB.R] = rgb.Red; dst[RGB.G] = rgb.Green; dst[RGB.B] = rgb.Blue; } dst += offset; ch += offsetCh; } if ( chData != null ) { // unlock channelImage.UnlockBits( chData ); } }
// Process the filter private unsafe void ProcessFilter( BitmapData data ) { int width = data.Width; int height = data.Height; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); int offset = data.Stride - width * 3; double ky = 0, by = 0; double kcb = 0, bcb = 0; double kcr = 0, bcr = 0; // Y line params if ( inY.Max != inY.Min ) { ky = ( outY.Max - outY.Min ) / ( inY.Max - inY.Min ); by = outY.Min - ky * inY.Min; } // Cb line params if ( inCb.Max != inCb.Min ) { kcb = ( outCb.Max - outCb.Min ) / ( inCb.Max - inCb.Min ); bcb = outCb.Min - kcb * inCb.Min; } // Cr line params if ( inCr.Max != inCr.Min ) { kcr = ( outCr.Max - outCr.Min ) / ( inCr.Max - inCr.Min ); bcr = outCr.Min - kcr * inCr.Min; } // do the job byte * ptr = (byte *) data.Scan0.ToPointer( ); // for each row for ( int y = 0; y < height; y++ ) { // for each pixel for ( int x = 0; x < width; x++, ptr += 3 ) { rgb.Red = ptr[RGB.R]; rgb.Green = ptr[RGB.G]; rgb.Blue = ptr[RGB.B]; // convert to YCbCr AForge.Imaging.ColorConverter.RGB2YCbCr( rgb, ycbcr ); // correct Y if ( ycbcr.Y >= inY.Max ) ycbcr.Y = outY.Max; else if ( ycbcr.Y <= inY.Min ) ycbcr.Y = outY.Min; else ycbcr.Y = ky * ycbcr.Y + by; // correct Cb if ( ycbcr.Cb >= inCb.Max ) ycbcr.Cb = outCb.Max; else if ( ycbcr.Cb <= inCb.Min ) ycbcr.Cb = outCb.Min; else ycbcr.Cb = kcb * ycbcr.Cb + bcb; // correct Cr if ( ycbcr.Cr >= inCr.Max ) ycbcr.Cr = outCr.Max; else if ( ycbcr.Cr <= inCr.Min ) ycbcr.Cr = outCr.Min; else ycbcr.Cr = kcr * ycbcr.Cr + bcr; // convert back to RGB AForge.Imaging.ColorConverter.YCbCr2RGB( ycbcr, rgb ); ptr[RGB.R] = rgb.Red; ptr[RGB.G] = rgb.Green; ptr[RGB.B] = rgb.Blue; } ptr += offset; } }
/// <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 YCbCr FromRGB(Color rgb, YCbCr ycbcr) { float r = (float)rgb.R / 255; float g = (float)rgb.G / 255; float b = (float)rgb.B / 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); 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> /// /// <returns>Returns <see cref="YCbCr"/> instance, which represents converted color value.</returns> /// public static YCbCr FromRGB(Color rgb) { YCbCr ycbcr = new YCbCr(); FromRGB(rgb, ycbcr); return ycbcr; }
public Image process(Image imageIn) { Color rgb = new Color(); YCbCr ycbcr = new YCbCr(); float ky = 0, by = 0; float kcb = 0, bcb = 0; float kcr = 0, bcr = 0; // Y line parameters if (inY.Max != inY.Min) { ky = (outY.Max - outY.Min) / (inY.Max - inY.Min); by = outY.Min - ky * inY.Min; } // Cb line parameters if (inCb.Max != inCb.Min) { kcb = (outCb.Max - outCb.Min) / (inCb.Max - inCb.Min); bcb = outCb.Min - kcb * inCb.Min; } // Cr line parameters if (inCr.Max != inCr.Min) { kcr = (outCr.Max - outCr.Min) / (inCr.Max - inCr.Min); bcr = outCr.Min - kcr * inCr.Min; } for (int x = 0; x < imageIn.getWidth(); x++) { for (int y = 0; y < imageIn.getHeight(); y++) { rgb.R = (byte)imageIn.getRComponent(x, y); rgb.G = (byte)imageIn.getGComponent(x, y); rgb.B = (byte)imageIn.getBComponent(x, y); // convert to YCbCr ycbcr = YCbCr.FromRGB(rgb, ycbcr); // correct Y if (ycbcr.Y >= inY.Max) ycbcr.Y = outY.Max; else if (ycbcr.Y <= inY.Min) ycbcr.Y = outY.Min; else ycbcr.Y = ky * ycbcr.Y + by; // correct Cb if (ycbcr.Cb >= inCb.Max) ycbcr.Cb = outCb.Max; else if (ycbcr.Cb <= inCb.Min) ycbcr.Cb = outCb.Min; else ycbcr.Cb = kcb * ycbcr.Cb + bcb; // correct Cr if (ycbcr.Cr >= inCr.Max) ycbcr.Cr = outCr.Max; else if (ycbcr.Cr <= inCr.Min) ycbcr.Cr = outCr.Min; else ycbcr.Cr = kcr * ycbcr.Cr + bcr; // convert back to RGB rgb = YCbCr.ToRGB(ycbcr, rgb); imageIn.setPixelColor(x, y, rgb.R, rgb.G, rgb.B); } } return imageIn; }
/// <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 Color ToRGB(YCbCr ycbcr, Color 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.R = (byte)(r * 255); rgb.G = (byte)(g * 255); rgb.B = (byte)(b * 255); //rgb.Alpha = 255; return rgb; }
// Process the filter private unsafe void ProcessFilter( BitmapData data ) { int width = data.Width; int height = data.Height; RGB rgb = new RGB( ); YCbCr ycbcr = new YCbCr( ); int offset = data.Stride - width * 3; bool updated; // do the job byte * ptr = (byte *) data.Scan0.ToPointer( ); // for each row for ( int y = 0; y < height; y++ ) { // for each pixel for ( int x = 0; x < width; x++, ptr += 3 ) { updated = false; rgb.Red = ptr[RGB.R]; rgb.Green = ptr[RGB.G]; rgb.Blue = ptr[RGB.B]; // convert to YCbCr AForge.Imaging.ColorConverter.RGB2YCbCr( rgb, ycbcr ); // check YCbCr values if ( ( ycbcr.Y >= yRange.Min ) && ( ycbcr.Y <= yRange.Max ) && ( ycbcr.Cb >= cbRange.Min ) && ( ycbcr.Cb <= cbRange.Max ) && ( ycbcr.Cr >= crRange.Min ) && ( ycbcr.Cr <= crRange.Max ) ) { if ( !fillOutsideRange ) { if ( updateY ) ycbcr.Y = fillY; if ( updateCb ) ycbcr.Cb = fillCb; if ( updateCr ) ycbcr.Cr = fillCr; updated = true; } } else { if ( fillOutsideRange ) { if ( updateY ) ycbcr.Y = fillY; if ( updateCb ) ycbcr.Cb = fillCb; if ( updateCr ) ycbcr.Cr = fillCr; updated = true; } } if ( updated ) { // convert back to RGB AForge.Imaging.ColorConverter.YCbCr2RGB( ycbcr, rgb ); ptr[RGB.R] = rgb.Red; ptr[RGB.G] = rgb.Green; ptr[RGB.B] = rgb.Blue; } } ptr += offset; } }