Beispiel #1
0
        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();
        }
Beispiel #2
0
 public ColorClose(Pixel key, int tola, int tolb)
 {
     _key = key.YCbCr();
     _tola = tola;
     _tolb = tolb;
     _tolba = _tolb - _tola;
 }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #7
0
            /// <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);
            }
Beispiel #8
0
        /// <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);
            }
        }
Beispiel #10
0
        /// <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));
        }
Beispiel #11
0
        /// <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));
        }
Beispiel #12
0
        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));
        }
Beispiel #16
0
        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));
        }
Beispiel #20
0
        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);
            }
        }
Beispiel #21
0
        /// <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);
        }
Beispiel #22
0
            /// <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));
        }
Beispiel #24
0
            /// <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);
            }
Beispiel #25
0
        /// <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));
        }
Beispiel #26
0
        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);
        }
Beispiel #27
0
            /// <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 );
        }
Beispiel #33
0
        /// <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;
            }
        }
Beispiel #34
0
        /// <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;
    }
Beispiel #38
0
        /// <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 );
            }
        }
Beispiel #39
0
        // 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;
            }
        }
    /// <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);
    }