/// <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 stride = image.Stride;
            int offset = stride - rect.Width * pixelSize;

            // levels linear correction filter is going to be used on STEP 2
            LevelsLinear levelsLinear = new LevelsLinear();

            // STEP 1 - search for min and max pixel values
            byte *ptr = (byte *)image.ImageData.ToPointer();

            // check image format
            if (image.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // allign pointer to the first pixel to process
                ptr += (startY * stride + startX);

                byte min = 255;
                byte max = 0;

                for (int y = startY; y < stopY; y++)
                {
                    for (int x = startX; x < stopX; x++, ptr++)
                    {
                        byte value = *ptr;

                        if (value < min)
                        {
                            min = value;
                        }

                        if (value > max)
                        {
                            max = value;
                        }
                    }
                    ptr += offset;
                }

                levelsLinear.InGray = new IntRange(min, max);
            }
            else
            {
                // allign pointer to the first pixel to process
                ptr += (startY * stride + startX * pixelSize);

                byte minR = 255, minG = 255, minB = 255;
                byte maxR = 0, maxG = 0, maxB = 0;

                for (int y = startY; y < stopY; y++)
                {
                    for (int x = startX; x < stopX; x++, ptr += pixelSize)
                    {
                        // red
                        byte value = ptr[RGB.R];

                        if (value < minR)
                        {
                            minR = value;
                        }

                        if (value > maxR)
                        {
                            maxR = value;
                        }

                        // green
                        value = ptr[RGB.G];

                        if (value < minG)
                        {
                            minG = value;
                        }

                        if (value > maxG)
                        {
                            maxG = value;
                        }

                        // blue
                        value = ptr[RGB.B];

                        if (value < minB)
                        {
                            minB = value;
                        }

                        if (value > maxB)
                        {
                            maxB = value;
                        }
                    }
                    ptr += offset;
                }

                levelsLinear.InRed   = new IntRange(minR, maxR);
                levelsLinear.InGreen = new IntRange(minG, maxG);
                levelsLinear.InBlue  = new IntRange(minB, maxB);
            }

            // STEP 2 - run levels linear correction
            levelsLinear.ApplyInPlace(image, rect);
        }
 /// <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)
 {
     baseFilter.ApplyInPlace(image, rect);
 }
        /// <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 stride = image.Stride;
            int offset = stride - rect.Width * pixelSize;

            // levels linear correction filter is going to be used on STEP 2
            LevelsLinear levelsLinear = new LevelsLinear();

            // STEP 1 - search for min and max pixel values
            byte* ptr = (byte*)image.ImageData.ToPointer();

            // check image format
            if (image.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // allign pointer to the first pixel to process
                ptr += (startY * stride + startX);

                byte min = 255;
                byte max = 0;

                for (int y = startY; y < stopY; y++)
                {
                    for (int x = startX; x < stopX; x++, ptr++)
                    {
                        byte value = *ptr;

                        if (value < min)
                            min = value;

                        if (value > max)
                            max = value;
                    }
                    ptr += offset;
                }

                levelsLinear.InGray = new IntRange(min, max);
            }
            else
            {
                // allign pointer to the first pixel to process
                ptr += (startY * stride + startX * pixelSize);

                byte minR = 255, minG = 255, minB = 255;
                byte maxR = 0, maxG = 0, maxB = 0;

                for (int y = startY; y < stopY; y++)
                {
                    for (int x = startX; x < stopX; x++, ptr += pixelSize)
                    {
                        // red
                        byte value = ptr[RGB.R];

                        if (value < minR)
                            minR = value;

                        if (value > maxR)
                            maxR = value;

                        // green
                        value = ptr[RGB.G];

                        if (value < minG)
                            minG = value;

                        if (value > maxG)
                            maxG = value;

                        // blue
                        value = ptr[RGB.B];

                        if (value < minB)
                            minB = value;

                        if (value > maxB)
                            maxB = value;
                    }
                    ptr += offset;
                }

                levelsLinear.InRed = new IntRange(minR, maxR);
                levelsLinear.InGreen = new IntRange(minG, maxG);
                levelsLinear.InBlue = new IntRange(minB, maxB);
            }

            // STEP 2 - run levels linear correction
            levelsLinear.ApplyInPlace(image, rect);
        }