Accord.Imaging.Filters.YCbCrReplaceChannel.ProcessFilter C# (CSharp) Method

ProcessFilter() protected method

Process the filter on the specified image.
Channel image was not specified. Channel image size does not match source /// image size.
protected ProcessFilter ( UnmanagedImage image, Rectangle rect ) : void
image UnmanagedImage Source image data.
rect System.Drawing.Rectangle Image rectangle for processing by the filter.
return void
        protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect)
        {
            if ((channelImage == null) && (unmanagedChannelImage == null))
                throw new InvalidOperationException("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
                    Accord.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
                    Accord.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);
            }
        }
    }