protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            if(Mask == null)
            {
                //copy all pixel
                Array.Copy(sourcePixelRegion.ImagePixels,targetPixelRegion.ImagePixels,sourcePixelRegion.ImagePixels.Length);
                return;
            }

            //create grayscale buffer
            var buffer = new Byte[(int)(sourcePixelRegion.Bounds.Width*sourcePixelRegion.Bounds.Height)];

            //interface grayscale buffer
            var bitmapMask = new Bitmap(
                new Windows.Foundation.Size(sourcePixelRegion.Bounds.Width, sourcePixelRegion.Bounds.Height),
                ColorMode.Gray8,
                (uint)sourcePixelRegion.Bounds.Width,
                buffer.AsBuffer());
            //load grayscale buffer
            Mask.GetBitmapAsync(bitmapMask,OutputOption.Stretch).AsTask().Wait();

            sourcePixelRegion.ForEachRow((index, width, pos) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint color = sourcePixelRegion.ImagePixels[index];

                    // copy grayscale buffer to alpha channel
                    var a = buffer[index];
                    uint rgb = (color & 0x00FFFFFF);
                    targetPixelRegion.ImagePixels[index] = rgb | (uint)(a << 24);
                }
            });
        }
            protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
            {
                targetPixelRegion.ForEachRow((index, width, position) =>
                {
                    for (int i = 0; i < width; ++i)
                    {
                        var pixel = sourcePixelRegion.ImagePixels[index + i];

                        uint red = (pixel >> 16) & 0x000000FF;
                        uint green = (pixel >> 8) & 0x000000FF;
                        uint blue = (pixel) & 0x000000FF;

                        int average = (int)(0.0722 * blue + 0.7152 * green + 0.2126 * red); // weighted average component
                        pixel = (uint)(0xff000000 | average | (average << 8) | (average << 16)); // use average for each color component

                        if (average > 150)
                            pixel = (uint)(0xffffffff);
                        else
                            pixel = (uint)(0xff000000);

                        targetPixelRegion.ImagePixels[index + i] = pixel;
                    }

                });
            }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint currentPixel = sourcePixels[index]; // get the current pixel

                    if (!currentPixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                        uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                        uint blue = currentPixel & 0x000000ff; // blue color component

                        // Take the percentage of each color component and add it to itself
                        // ex. A -1.0 or -100% will completely reduce a color component to 0
                        // ex. A 1.0 or 100% will double the value of the color component, up to the maximum of 255 of course
                        red = (uint)Math.Max(0, Math.Min(255, (red + (red * m_RedPercentage))));
                        green = (uint)Math.Max(0, Math.Min(255, (green + (green * m_GreenPercentage))));
                        blue = (uint)Math.Max(0, Math.Min(255, (blue + (blue * m_BluePercentage))));

                        // Reassembling each component back into a pixel for the target pixel location
                        targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                    }
                }
            });
        }
Beispiel #4
0
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;
            var row = 0;
            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                if (row % 2 == 0)
                {
                    for (int y = 0; y < width; ++y, ++index)
                    {
                        targetPixels[index] = ResultPixel(sourcePixels[index]);
                    }
                }
                else
                {
                    for (int x = 0; x < width; ++x, ++index)
                    {
                        if (x % 2 == 0)
                            targetPixels[index] = ResultPixel(sourcePixels[index]);
                        else
                            targetPixels[index] = sourcePixels[index];
                    }
                }
                row++;

            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            sourcePixelRegion.ForEachRow((index, width, pos) =>
            {

                for (int x = 0; x < width; ++x, ++index)
                {
                    uint color = sourcePixelRegion.ImagePixels[index];

                    // Extract color channel values
                    var a = (byte)((color >> 24) & 255);
                    var r = (byte)((color >> 16) & 255);
                    var g = (byte)((color >> 8) & 255);
                    var b = (byte)((color) & 255);

                    r = (byte)Math.Min(255, r * factor);
                    g = (byte)Math.Min(255, g * factor);
                    b = (byte)Math.Min(255, b * factor);

                    // Combine modified color channels
                    var newColor = (uint)(b | (g << 8) | (r << 16) | (a << 24));

                    targetPixelRegion.ImagePixels[index] = newColor;
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            float[] vet = new float[256];
            int[] hist = new int[256];

            // simply computes the grayscale image histogram
            sourcePixelRegion.ForEachRow((index, width, pos) =>
            {
                for (int x = 0; x < width; x += 3, index += 3)
                {
                    uint currentPixel = sourcePixelRegion.ImagePixels[index];

                    uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                    uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                    uint blue = currentPixel & 0x000000ff; // blue color component

                    //luminance formula
                    var p = (byte)(0.21 * red + 0.71 * green + 0.07 * blue);
                    hist[p]++;
                }
            });

            float p1, p2, p12;
            int k;

            // loop through all possible t values and maximize between class variance
            for (k = 1; k != 255; k++)
            {
                p1 = Px(0, k, hist);
                p2 = Px(k + 1, 255, hist);
                p12 = p1 * p2;
                if (p12 == 0)
                    p12 = 1;
                float diff = (Mx(0, k, hist) * p2) - (Mx(k + 1, 255, hist) * p1);
                vet[k] = (float)diff * diff / p12;
            }

            _threshold = (byte)findMax(vet, 256);

            uint white = 0xff000000 | (255 << 16) | (255 << 8) | 255;
            uint black = 0xff000000 | (0 << 16) | (0 << 8) | 0;

            // simple routine for thresholding
            sourcePixelRegion.ForEachRow((index, width, pos) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint currentPixel = sourcePixelRegion.ImagePixels[index];

                    uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                    uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                    uint blue = currentPixel & 0x000000ff; // blue color component

                    if ((byte)(0.21 * red + 0.71 * green + 0.07 * blue) < _threshold)
                        sourcePixelRegion.ImagePixels[index] = black;
                    else
                        sourcePixelRegion.ImagePixels[index] = white;
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // This only works for a realtime feed.  It does not work with static images.
                    // 16-17 FPS with built-in NegativeFilter() and 15 FPS with this technique on Lumia 920
                    //targetPixels[index] = ~sourcePixels[index];

                    // 16-17 FPS with built-in NegativeFilter() and 13-14 FPS with this technique on Lumia 920
                    // This techinque will work with both a realtime feed and static images.
                    ///*
                    uint pixel = sourcePixels[index]; // get the current pixel

                    if (!pixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        // Flip the bits of the pixel to create the negative effect
                        pixel = ~pixel;

                        // Assign the pixels back by each component so we can ensure the alpha channel
                        // is at 255. Otherwise the image will not be visible if it is static.
                        targetPixels[index] = 0xff000000 | (pixel & 0x00ff0000) | (pixel & 0x0000ff00) | pixel & 0x000000ff;
                    }
                    //*/
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // NOTE: Just pulling out the color components and reassembling them brings you down to 14-15 FPS
                    uint currentPixel = sourcePixels[index]; // get the current pixel

                    if (!currentPixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                        uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                        uint blue = currentPixel & 0x000000ff; // blue color component

                        // Original accidental code
                        //red = Math.Max(0, Math.Min(255, (uint)(int)(red - m_factor)));
                        //green = Math.Max(0, Math.Min(255, (uint)(int)(green - m_factor)));
                        //blue = Math.Max(0, Math.Min(255, (uint)(int)(blue - m_factor)));

                        // Max out any color component that falls below zero - 12-13 FPS
                        red = (red < m_factor ? 255 : red - m_factor);
                        green = (green < m_factor ? 255 : green - m_factor);
                        blue = (blue < m_factor ? 255 : blue - m_factor);

                        // Reassemble each component back into a pixel and assign it to the equivalent output image location
                        targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                    }
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            int rowIndex = 0;
            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                // get the vertical midpoint >>> L = (P / W) >>> V = (L / 2)
                int verticalMidPoint = (sourcePixels.Length / width) / 2;
                // get the horizontal midpoint >>> M = (W / 2)
                int horizontalMidPoint = width / 2;

                if (m_MirrorType.Equals(MirrorType.Vertical))
                {
                    for (int x = 0; x < width; ++x, ++index)
                    {
                        if (rowIndex < verticalMidPoint)
                        {
                            // Just keep the first half of the column as is
                            targetPixels[index] = sourcePixels[index];
                        }
                        else
                        {
                            // Now we start repeating the mirror image from the first half of the column
                            // index - (((i - V) * 2 * W) - 1)
                            int sourceIndex = index - ((rowIndex - verticalMidPoint) * 2 * width) - 1;
                            if (sourceIndex > 0)
                            {
                                targetPixels[index] = sourcePixels[sourceIndex];
                            }
                        }
                    }
                }
                else
                {
                    for (int x = 0; x < width; ++x, ++index)
                    {
                        if (x < horizontalMidPoint)
                        {
                            // Just keep the first half of the row as is
                            targetPixels[index] = sourcePixels[index];
                        }
                        else
                        {
                            // Now we start repeating the mirror image from the first half of the row
                            // index - (((x - H) * 2) - 1)
                            int sourceIndex = index - ((x - horizontalMidPoint) * 2) - 1;
                            if (sourceIndex > 0)
                            {
                                targetPixels[index] = sourcePixels[sourceIndex];
                            }
                        }
                    }
                }
                rowIndex++;
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // 16-17 FPS with built-in GrayscaleFilter() and 11 FPS with this technique on Lumia 920
                    uint currentPixel = sourcePixels[index]; // get the current pixel

                    if (!currentPixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                        uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                        uint blue = currentPixel & 0x000000ff; // blue color component
                        uint grayscaleAverage = 0;

                        // Calculate the weighted avearge of all the color components
                        // REFERENCES:
                        //      http://en.wikipedia.org/wiki/Grayscale
                        //      http://www.plosone.org/article/info%3Adoi%2F10.1371%2Fjournal.pone.0029740
                        //      http://vcg.isti.cnr.it/~corsini/publications/grayscale_matching_preprint.pdf

                        if (m_SquareCalc) // You drop down 1 FPS to 7-8 FPS using the square calc method
                        {
                            grayscaleAverage = (uint)Math.Max(0, Math.Min(255, (
                                Math.Sqrt((m_RedPercentage * red) * (m_RedPercentage * red) +
                                (m_GreenPercentage * green) * (m_GreenPercentage * green) +
                                (m_BluePercentage * blue) * (m_BluePercentage * blue)
                                ))));
                        }
                        else
                        {
                            grayscaleAverage = (uint)Math.Max(0, Math.Min(255, (
                                (m_RedPercentage * red) +
                                (m_GreenPercentage * green) +
                                (m_BluePercentage * blue)
                                )));

                            //grayscaleAverage = (uint)(red * 0.33 + green * 0.50 + blue * 0.16); // accurate approximation algo
                            //grayscaleAverage = (red + red + blue + green + green + green) / 6; // less accurate approximation algo

                            //grayscaleAverage = (uint)(red * 0.375 + green * 0.50 + blue * 0.125); // less accurate approximation algo 2
                            //grayscaleAverage = (red + red + red + blue + green + green + green + green) >> 3; // less accurate approximation algo 2
                        }

                        // Assign the result to each component
                        //red = green = blue = grayscaleAverage;

                        // Reassembling the average for each component back into a pixel for the target pixel location
                        //targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                        targetPixels[index] = 0xff000000 | (grayscaleAverage << 16) | (grayscaleAverage << 8) | grayscaleAverage;
                    }
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            uint maskSize = Size % 2 == 0 ? Size + 1 : Size;

            uint width = (uint)sourcePixelRegion.Bounds.Width;
            uint height = (uint)sourcePixelRegion.Bounds.Height;

            List<Tuple<int, double, byte>> maskIndex = new List<Tuple<int, double, byte>>();

            uint r2 = maskSize * maskSize;

            //compute circle mask
            for (int i = -(int)maskSize; i <= maskSize; ++i)
                for (int j = -(int)maskSize; j <= maskSize; ++j)
                {
                    int d2 = i * i + j * j;
                    if (d2 == 0 || d2 > r2)
                        continue;

                    maskIndex.Add(new Tuple<int, double, byte>(
                        i * (int)width + j,
                        d2 / (double)r2,
                        (byte)(255 * Math.Pow(d2 / (double)r2 / 0.5, 0.5) + 0.5)));
                }

            for (uint i = maskSize; i < height - maskSize; ++i)
                for (uint j = maskSize; j < width - maskSize; ++j)
                {
                    uint index = i * width + j;

                    if (sourcePixelRegion.ImagePixels[index] >> 24 > 128)
                    {

                        Tuple<int, double, byte> p = null;
                        foreach (var id in maskIndex)
                        {

                            if (sourcePixelRegion.ImagePixels[index + id.Item1] >> 24 < 128)
                            {
                                if (p == null || id.Item2 < p.Item2)
                                    p = id;
                            }
                        }
                        if (p != null && p.Item2 <= 0.5)
                        {

                            var alpha = p.Item3;
                            uint color = sourcePixelRegion.ImagePixels[index];
                            uint rgb = (color & 0x00FFFFFF);
                            targetPixelRegion.ImagePixels[index] = rgb | (uint)(alpha << 24);
                            continue;
                        }
                        targetPixelRegion.ImagePixels[index] = sourcePixelRegion.ImagePixels[index];
                    }
                }
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            uint color = ((uint)Color.A << 24) | ((uint)Color.R << 16) | ((uint)Color.G << 8) | ((uint)Color.B);
            uint maskSize = Size % 2 == 0 ? Size + 1 : Size;

            uint width = (uint)sourcePixelRegion.Bounds.Width;
            uint height = (uint)sourcePixelRegion.Bounds.Height;

            List<int> maskIndex = new List<int>();

            uint maskSize_2 = maskSize / 2;

            uint r2 = maskSize_2 * maskSize_2;

            //compute circle mask
            for (int i = -(int)maskSize_2; i <= maskSize_2; ++i)
                for (int j = -(int)maskSize_2; j <= maskSize_2; ++j)
                {
                    int d2 = i * i + j * j;
                    if (d2 == 0 || d2 > r2)
                        continue;

                    maskIndex.Add(i * (int)sourcePixelRegion.Pitch + j);
                }

            for (uint i = 0; i < height ; ++i)
                for (uint j = 0; j < width ; ++j)
                {
                    uint index_source = (uint) (sourcePixelRegion.StartIndex + i * sourcePixelRegion.Pitch + j);
                    uint index_target = (uint) (targetPixelRegion.StartIndex + i * targetPixelRegion.Pitch + j);

                    if (sourcePixelRegion.ImagePixels[index_source] >> 24 < 128)
                    {

                        bool NoALphaPixelFound = false;
                        foreach (int id in maskIndex)
                        {

                            if (sourcePixelRegion.ImagePixels[index_source + id] >> 24 > 128)
                            {
                                NoALphaPixelFound = true;
                                break;
                            }
                        }
                        if (NoALphaPixelFound)
                        {
                            targetPixelRegion.ImagePixels[index_target] = color;
                            continue;
                        }
                    }
                        targetPixelRegion.ImagePixels[index_target] = sourcePixelRegion.ImagePixels[index_source];

                }
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;
            int rowindex = 0;
            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                // normalize y coordinate to -1 ... 1 
                double ny = ((2 * rowindex) / sourcePixelRegion.ImageSize.Height) - 1;
                // for each column 
                for (int x = 0; x < sourcePixelRegion.ImageSize.Width; x++, index++)
                {
                    // normalize x coordinate to -1 ... 1 
                    double nx = ((2 * x) / sourcePixelRegion.ImageSize.Width) - 1;
                    // calculate distance from center (0,0)
                    double radius = Math.Sqrt(nx * nx + ny * ny);

                    bool fillBlack = true;
                    // discard pixels outside from circle! 
                    if (0 <= radius && radius <= 1)
                    {
                        //compute the distorted radius
                        double newRadius = (radius + (1 - Math.Sqrt(1 - radius * radius))) / 2;
                        // discard radius greater than 1, which will result in black zones
                        if (newRadius <= 1)
                        {
                            // calculate the angle for polar coordinates 
                            double theta = Math.Atan2(ny, nx);
                            // calculate new x,y position using new distance in same angle 
                            double nxn = newRadius * Math.Cos(theta);
                            double nyn = newRadius * Math.Sin(theta);
                            // map from -1 ... 1 to image coordinates
                            int x2 = (int)(((nxn + 1) * sourcePixelRegion.ImageSize.Width) / 2);
                            int y2 = (int)(((nyn + 1) * sourcePixelRegion.ImageSize.Height) / 2);
                            // find (x2,y2) position from source pixels 
                            int srcpos = (int)(y2 * sourcePixelRegion.ImageSize.Width + x2);
                            // make sure that position stays within arrays 
                            if (srcpos >= 0 & srcpos < sourcePixelRegion.ImageSize.Width * sourcePixelRegion.ImageSize.Height)
                            {
                                targetPixels[index] = sourcePixels[srcpos];
                                fillBlack = false;
                            }
                        }
                    }
                    
                    if (fillBlack)
                    {
                        targetPixels[index] = 0xff000000;
                    }
                }
                rowindex++;
            });
        }
    protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
    {
        var sourcePixels = sourcePixelRegion.ImagePixels;
        var targetPixels = targetPixelRegion.ImagePixels;

        sourcePixelRegion.ForEachRow((index, width, position) =>
        {
            for (int x = 0; x < width; ++x, ++index)
            {
                targetPixels[index] = ~sourcePixels[index];
            }
        });
    }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // the only supported color format is ColorFormat.Bgra8888

                    uint pixel = sourcePixels[index] & 0xffff0000; //Green & Blue components are removed using Bitwise-AND operator

                    targetPixels[index] = pixel;
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            targetPixelRegion.ForEachRow((index, width, position) =>
            {
                for (int i = 0; i < width; ++i)
                {
                    var pixel = sourcePixelRegion.ImagePixels[index + i];

                    uint red   = (pixel >> 16) & 0x000000FF;
                    uint green = (pixel >> 8) & 0x000000FF;
                    uint blue  = (pixel) & 0x000000FF;

                    int average = (int)(0.0722 * blue + 0.7152 * green + 0.2126 * red);                                         // weighted average component
                    targetPixelRegion.ImagePixels[index + i] = (uint)(0xff000000 | average | (average << 8) | (average << 16)); // use average for each color component
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            int rowIndex = 0;
            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                if ((rowIndex % m_ProcessEveryNthRow).Equals(m_RowModuloTarget)) // only process on every other Nth pixel per row
                {
                    for (int x = 0; x < width; ++x, ++index)
                    {
                        if ((x % m_ProcessEveryNthColumn).Equals(m_ColumnModuloTarget)) // only process on every other Nth pixel per column
                        {
                            uint currentPixel = sourcePixels[index]; // get the current pixel
                            uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                            uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                            uint blue = currentPixel & 0x000000ff; // blue color component

                            if (m_BrightnessPercentage < 0)
                            {
                                // Dimming the image - A value of -1 or -100%, will completely reduce all colors to 0
                                // Reduce each color component by the passed in percentage of the amount of color
                                // it is currently displaying.
                                red = (uint)Math.Max(0, Math.Min(255, (red + (red * m_BrightnessPercentage))));
                                green = (uint)Math.Max(0, Math.Min(255, (green + (green * m_BrightnessPercentage))));
                                blue = (uint)Math.Max(0, Math.Min(255, (blue + (blue * m_BrightnessPercentage))));
                            }
                            else
                            {
                                // Brightening the image - A value of 1 or 100%, will completely increase all colors to 255
                                // Increase each color component by the passed in percentage of the amount of color
                                // is has left before it reaches the max of 255.
                                red = (uint)Math.Max(0, Math.Min(255, (red + ((255 - red) * m_BrightnessPercentage))));
                                green = (uint)Math.Max(0, Math.Min(255, (green + ((255 - green) * m_BrightnessPercentage))));
                                blue = (uint)Math.Max(0, Math.Min(255, (blue + ((255 - blue) * m_BrightnessPercentage))));
                            }

                            // Reassemble each component back into a pixel and assign it to the equivalent output image location
                            targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                        }
                    }
                }
                rowIndex++;
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint currentPixel = sourcePixels[index]; // get the current pixel

                    if (!currentPixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                        uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                        uint blue = currentPixel & 0x000000ff; // blue color component

                        if (m_BrightnessPercentage < 0)
                        {
                            // Dimming the image - A value of -1 or -100%, will completely reduce all colors to 0
                            // Reduce each color component by the passed in percentage of the amount of color
                            // it is currently displaying.
                            red = (uint)Math.Max(0, (red + (red * m_BrightnessPercentage)));
                            green = (uint)Math.Max(0, (green + (green * m_BrightnessPercentage)));
                            blue = (uint)Math.Max(0, (blue + (blue * m_BrightnessPercentage)));
                        }
                        else
                        {
                            // Brightening the image - A value of 1 or 100%, will completely increase all colors to 255
                            // Increase each color component by the passed in percentage of the amount of color
                            // is has left before it reaches the max of 255.
                            red = (uint)Math.Min(255, (red + ((255 - red) * m_BrightnessPercentage)));
                            green = (uint)Math.Min(255, (green + ((255 - green) * m_BrightnessPercentage)));
                            blue = (uint)Math.Min(255, (blue + ((255 - blue) * m_BrightnessPercentage)));
                        }

                        // Reassembling each component back into a pixel for the target pixel location
                        targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                    }
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint currentPixel = sourcePixels[index]; // get the current pixel

                    if (!currentPixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                        uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                        uint blue = currentPixel & 0x000000ff; // blue color component

                        // RGB to YIQ
                        uint Y = (uint)(0.299 * red + 0.587 * green + 0.114 * blue);
                        uint I = (uint)Math.Max((0.596 * red - 0.274 * green - 0.322 * blue), 0);
                        //uint Q = (uint)Math.Max((0.212 * red - 0.523 * green + 0.311 * blue), 0); // No need to calculate since we zero out
                        //uint Q = 0; // No need to even create the variable if we are not using the exact original formula

                        // Update for Sepia look
                        I = m_Intensity;

                        // YIQ to RGB
                        // Original formula for converting back from YIQ to RGB
                        //red = (uint)Math.Min((1.0 * Y + 0.956 * I + 0.621 * Q), 255);
                        //green = (uint)Math.Min(Math.Max((1.0 * Y - 0.272 * I - 0.647 * Q), 0), 255);
                        //blue = (uint)Math.Min(Math.Max((1.0 * Y - 1.105 * I + 1.702 * Q), 0), 255);
                        // No need to waste multiplications with 1.0 or with the Q component we zero out
                        red = (uint)Math.Min((Y + (0.956 * I)), 255);
                        green = (uint)Math.Min(Math.Max((Y - (0.272 * I)), 0), 255);
                        blue = (uint)Math.Min(Math.Max((Y - (1.105 * I)), 0), 255);

                        // Reassembling each component back into a pixel and assigning it to the output location
                        targetPixels[index] = 0xff000000 | (red << 16) | (green << 8) | blue;
                    }
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            m_ProcessEveryNthRow = m_Scale;
            m_ProcessEveryNthColumn = m_Scale;
            m_RowModuloTarget = m_ProcessEveryNthRow - 1;
            m_ColumnModuloTarget = m_ProcessEveryNthColumn - 1;

            int rowIndex = 0;
            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                if ((rowIndex % m_ProcessEveryNthRow).Equals(m_RowModuloTarget)) // only process on every other Nth pixel per row
                {
                    for (int x = 0; x < width; ++x, ++index)
                    {
                        if ((x % m_ProcessEveryNthColumn).Equals(m_ColumnModuloTarget)) // only process on every other Nth pixel per column
                        {
                            // Get the center pixel for the given scale we are working with, and manipulate as desired
                            int centerRowOffset = -1 * ((m_ProcessEveryNthRow - 1) / 2);
                            int centerColumnOffset = -1 * ((m_ProcessEveryNthColumn - 1) / 2);
                            uint targetPixel = sourcePixels[FindIndex(rowIndex, x, width, centerRowOffset, centerColumnOffset)];

                            // Get the top left position of the pixel block, given the current scale
                            int topRowOffset = -1 * (m_ProcessEveryNthRow - 1);
                            int leftColumnOffset = -1 * (m_ProcessEveryNthColumn - 1);

                            // Loop from the top left position down to the bottom right, where we stopped to process
                            for (int y1 = topRowOffset; y1 <= 0; y1++)
                            {
                                for (int x1 = leftColumnOffset; x1 <= 0; x1++)
                                {
                                    targetPixels[FindIndex(rowIndex, x, width, y1, x1)] = targetPixel;
                                }
                            }
                        }
                    }
                }
                rowIndex++;
            });
        }
		protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
		{
			for (int i = 0; i < sourcePixelRegion.ImagePixels.Length; i++)
			{
				uint newPixelValue = 0;

				for (int j = 0; j < 3; j++)
				{
					uint pixelValue = (sourcePixelRegion.ImagePixels[i] & (255u << (8 * j))) >> (8 * j);

					if (pixelValue > m_whiteThreshold)
					{
						pixelValue = 0;
					}

					newPixelValue += pixelValue << (8 * j);
				}

				targetPixelRegion.ImagePixels[i] = newPixelValue + (255u << 24);
			}
		}
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            for (int i = 0; i < sourcePixelRegion.ImagePixels.Length; i++)
            {
                uint newPixelValue = 0;

                for (int j = 0; j < 3; j++)
                {
                    uint pixelValue = (sourcePixelRegion.ImagePixels[i] & (255u << (8 * j))) >> (8 * j);

                    if (pixelValue > m_whiteThreshold)
                    {
                        pixelValue = 0;
                    }

                    newPixelValue += pixelValue << (8 * j);
                }

                targetPixelRegion.ImagePixels[i] = newPixelValue + (255u << 24);
            }
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    uint pixel = sourcePixels[index]; // get the current pixel

                    if (!pixel.Equals(0)) // Only process if it is not transparent and part of the image
                    {
                        uint red = (pixel & 0x00ff0000) >> 16; // red color component
                        uint green = (pixel & 0x0000ff00) >> 8; // green color component
                        uint blue = pixel & 0x000000ff; // blue color component

                        // Calculate the weighted avearge of all the color components
                        // REFERENCE: http://en.wikipedia.org/wiki/Grayscale
                        uint grayscaleAverage = (uint)Math.Max(0, Math.Min(255, (
                            m_RedPercentage * red +
                            m_GreenPercentage * green +
                            m_BluePercentage * blue)));

                        // Assign the result to each component
                        red = green = blue = grayscaleAverage;

                        // Reassembling each component back into a pixel
                        pixel = 0xff000000 | (red << 16) | (green << 8) | blue;

                        // Flip the bits of the pixel to create the negative effect
                        pixel = ~pixel;

                        // Assign the pixels back by each component so we can ensure the alpha channel
                        // is at 255. Otherwise the image will not be visible if it is static.
                        targetPixels[index] = 0xff000000 | (pixel & 0x00ff0000) | (pixel & 0x0000ff00) | pixel & 0x000000ff;
                    }
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // the only supported color format is ColorFormat.Bgra8888

                    uint pixel = sourcePixels[index];
                    uint blue = pixel & 0x000000ff; // blue color component
                    uint green = (pixel & 0x0000ff00) >> 8; // green color component
                    uint red = (pixel & 0x00ff0000) >> 16; // red color component
                    uint average = (uint)(0.0722 * blue + 0.7152 * green + 0.2126 * red); // weighted average component
                    uint grayscale = 0xff000000 | average | (average << 8) | (average << 16); // use average for each color component

                    targetPixels[index] = ~grayscale; // use inverse grayscale
                }
            });
        }
Beispiel #25
0
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            var sourcePixels = sourcePixelRegion.ImagePixels;
            var targetPixels = targetPixelRegion.ImagePixels;

            sourcePixelRegion.ForEachRow((index, width, position) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    // the only supported color format is ColorFormat.Bgra8888

                    uint pixel     = sourcePixels[index];
                    uint blue      = pixel & 0x000000ff;                                      // blue color component
                    uint green     = (pixel & 0x0000ff00) >> 8;                               // green color component
                    uint red       = (pixel & 0x00ff0000) >> 16;                              // red color component
                    uint average   = (uint)(0.0722 * blue + 0.7152 * green + 0.2126 * red);   // weighted average component
                    uint grayscale = 0xff000000 | average | (average << 8) | (average << 16); // use average for each color component

                    targetPixels[index] = ~grayscale;                                         // use inverse grayscale
                }
            });
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            sourcePixelRegion.ForEachRow((index, width, pos) =>
            {
                for (int x = 0; x < width; ++x, ++index)
                {
                    Color c = ToColor(sourcePixelRegion.ImagePixels[index]);

                    Red[c.R]++;

                    Green[c.G]++;

                    Blue[c.B]++;

                    double luminance = 0.299 * c.R + 0.587 * c.G + 0.114 * c.B;
                    if (luminance < byte.MinValue)
                        luminance = byte.MinValue;
                    else if (luminance > byte.MaxValue)
                        luminance = byte.MaxValue;

                    Luminance[(byte)luminance]++;
                }
            });
        }
    protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
    {
        var sourcePixels = sourcePixelRegion.ImagePixels;
        var targetPixels = targetPixelRegion.ImagePixels;

        sourcePixelRegion.ForEachRow((index, width, position) =>
        {
            for (int x = 0; x < width; ++x, ++index)
            {
                uint currentPixel = sourcePixels[index]; // get the current pixel
                uint red = (currentPixel & 0x00ff0000) >> 16; // red color component
                uint green = (currentPixel & 0x0000ff00) >> 8; // green color component
                uint blue = currentPixel & 0x000000ff; // blue color component

                // Calculate the weighted avearge of all the color components and assign the result to each component
                // REFERENCE: http://en.wikipedia.org/wiki/Grayscale
                uint grayscaleAverage = (uint)(0.2126 * red + 0.7152 * green + 0.0722 * blue);
                red = green = blue = grayscaleAverage;

                uint newPixel = 0xff000000 | (red << 16) | (green << 8) | blue; // reassembling each component back into a pixel
                targetPixels[index] = newPixel; // assign the newPixel to the equivalent location in the output image
            }
        });
    }
        // Collect objects' rectangles
        private void CollectObjectsInfo(PixelRegion sourcePixelRegion)
        {
            int i = 0, label;

            // create object coordinates arrays
            int[] x1 = new int[objectsCount + 1];
            int[] y1 = new int[objectsCount + 1];
            int[] x2 = new int[objectsCount + 1];
            int[] y2 = new int[objectsCount + 1];

            int[] area = new int[objectsCount + 1];
            long[] xc = new long[objectsCount + 1];
            long[] yc = new long[objectsCount + 1];

            long[] meanR = new long[objectsCount + 1];
            long[] meanG = new long[objectsCount + 1];
            long[] meanB = new long[objectsCount + 1];

            long[] stdDevR = new long[objectsCount + 1];
            long[] stdDevG = new long[objectsCount + 1];
            long[] stdDevB = new long[objectsCount + 1];

            for (int j = 1; j <= objectsCount; j++)
            {
                x1[j] = imageWidth;
                y1[j] = imageHeight;
            }

            // color images
            byte r, g, b; // RGB value

            // walk through labels array
            for (int y = 0; y < imageHeight; y++)
            {
                for (int x = 0; x < imageWidth; x++, i++)
                {
                    // get current label
                    label = objectLabels[i];

                    // skip unlabeled pixels
                    if (label == 0)
                        continue;

                    // check and update all coordinates

                    if (x < x1[label])
                    {
                        x1[label] = x;
                    }
                    if (x > x2[label])
                    {
                        x2[label] = x;
                    }
                    if (y < y1[label])
                    {
                        y1[label] = y;
                    }
                    if (y > y2[label])
                    {
                        y2[label] = y;
                    }

                    area[label]++;
                    xc[label] += x;
                    yc[label] += y;

                    Color c = ToColor(sourcePixelRegion.ImagePixels[y * imageWidth + x]);
                    r = c.R;
                    g = c.G;
                    b = c.B;

                    meanR[label] += r;
                    meanG[label] += g;
                    meanB[label] += b;

                    stdDevR[label] += r * r;
                    stdDevG[label] += g * g;
                    stdDevB[label] += b * b;
                }
            }

            // create blobs
            blobs.Clear();

            for (int j = 1; j <= objectsCount; j++)
            {
                int blobArea = area[j];

                Blob blob = new Blob(j, new Rect(x1[j], y1[j], x2[j] - x1[j] + 1, y2[j] - y1[j] + 1));
                blob.Area = blobArea;
                blob.Fullness = (double)blobArea / ((x2[j] - x1[j] + 1) * (y2[j] - y1[j] + 1));
                blob.CenterOfGravity = new Point((float)xc[j] / blobArea, (float)yc[j] / blobArea);
                blob.ColorMean = Color.FromArgb(255, (byte)(meanR[j] / blobArea), (byte)(meanG[j] / blobArea), (byte)(meanB[j] / blobArea));
                blob.ColorStdDev = Color.FromArgb(
                    255,
                    (byte)(Math.Sqrt(stdDevR[j] / blobArea - blob.ColorMean.R * blob.ColorMean.R)),
                    (byte)(Math.Sqrt(stdDevG[j] / blobArea - blob.ColorMean.G * blob.ColorMean.G)),
                    (byte)(Math.Sqrt(stdDevB[j] / blobArea - blob.ColorMean.B * blob.ColorMean.B)));

                blobs.Add(blob);
            }
        }
        private void BuildObjectsMap(PixelRegion sourcePixelRegion)
        {
            // we don't want one pixel width images
            if (imageWidth == 1)
            {
                throw new Exception("BlobCounter cannot process images that are one pixel wide. Rotate the image or use RecursiveBlobCounter.");
            }

            int imageWidthM1 = imageWidth - 1;

            // allocate labels array
            objectLabels = new int[imageWidth * imageHeight];
            // initial labels count
            int labelsCount = 0;

            // create map
            int maxObjects = ((imageWidth / 2) + 1) * ((imageHeight / 2) + 1) + 1;
            int[] map = new int[maxObjects];

            // initially map all labels to themself
            for (int i = 0; i < maxObjects; i++)
            {
                map[i] = i;
            }

            // do the job
            int pos = 0;
            int p = 0;

            // color images
            int pixelSize = 1;
            int offset = imageWidth * pixelSize;

            int stride = imageWidth;
            int strideM1 = stride - pixelSize;
            int strideP1 = stride + pixelSize;

            // 1 - for pixels of the first row
            Color firstColor = ToColor(sourcePixelRegion.ImagePixels[pos]);

            if ((firstColor.R | firstColor.G | firstColor.B) != 0)
            {
                objectLabels[p] = ++labelsCount;
            }
            pos += pixelSize;
            ++p;

            for (int x = 1; x < imageWidth; x++, pos += pixelSize, p++)
            {
                Color color = ToColor(sourcePixelRegion.ImagePixels[pos]);

                // check if we need to label current pixel
                if ((color.R > backgroundThresholdR) ||
                     (color.G > backgroundThresholdG) ||
                     (color.B > backgroundThresholdB))
                {
                    Color prevColor = ToColor(sourcePixelRegion.ImagePixels[pos - 1]);
                    // check if the previous pixel already was labeled
                    if ((prevColor.R > backgroundThresholdR) ||
                         (prevColor.G > backgroundThresholdG) ||
                         (prevColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the previous
                        objectLabels[p] = objectLabels[p - 1];
                    }
                    else
                    {
                        // create new label
                        objectLabels[p] = ++labelsCount;
                    }
                }
            }

            // 2 - for other rows
            // for each row
            for (int y = 1; y < imageHeight; y++)
            {
                Color rowFirstColor = ToColor(sourcePixelRegion.ImagePixels[pos]);
                // for the first pixel of the row, we need to check
                // only upper and upper-right pixels
                if ((rowFirstColor.R > backgroundThresholdR) ||
                        (rowFirstColor.G > backgroundThresholdG) ||
                        (rowFirstColor.B > backgroundThresholdB))
                {
                    Color aboveColor = ToColor(sourcePixelRegion.ImagePixels[pos - stride]);
                    Color aboveRightColor = ToColor(sourcePixelRegion.ImagePixels[pos - strideM1]);
                    // check surrounding pixels
                    if ((aboveColor.R > backgroundThresholdR) ||
                         (aboveColor.G > backgroundThresholdG) ||
                         (aboveColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the above
                        objectLabels[p] = objectLabels[p - imageWidth];
                    }
                    else if ((aboveRightColor.R > backgroundThresholdR) ||
                              (aboveRightColor.G > backgroundThresholdG) ||
                              (aboveRightColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the above right
                        objectLabels[p] = objectLabels[p + 1 - imageWidth];
                    }
                    else
                    {
                        // create new label
                        objectLabels[p] = ++labelsCount;
                    }
                }
                pos += pixelSize;
                ++p;

                // check left pixel and three upper pixels for the rest of pixels
                for (int x = 1; x < imageWidth - 1; x++, pos += pixelSize, p++)
                {
                    Color color = ToColor(sourcePixelRegion.ImagePixels[pos]);
                    if ((color.R > backgroundThresholdR) ||
                         (color.G > backgroundThresholdG) ||
                         (color.B > backgroundThresholdB))
                    {
                        Color leftColor = ToColor(sourcePixelRegion.ImagePixels[pos - pixelSize]);
                        Color aboveLeftColor = ToColor(sourcePixelRegion.ImagePixels[pos - strideP1]);
                        Color aboveColor = ToColor(sourcePixelRegion.ImagePixels[pos - stride]);
                        Color aboveRightColor = ToColor(sourcePixelRegion.ImagePixels[pos - strideM1]);

                        // check surrounding pixels
                        if ((leftColor.R > backgroundThresholdR) ||
                             (leftColor.G > backgroundThresholdG) ||
                             (leftColor.B > backgroundThresholdB))
                        {
                            // label current pixel, as the left
                            objectLabels[p] = objectLabels[p - 1];
                        }
                        else if ((aboveLeftColor.R > backgroundThresholdR) ||
                                  (aboveLeftColor.G > backgroundThresholdG) ||
                                  (aboveLeftColor.B > backgroundThresholdB))
                        {
                            // label current pixel, as the above left
                            objectLabels[p] = objectLabels[p - 1 - imageWidth];
                        }
                        else if ((aboveColor.R > backgroundThresholdR) ||
                                  (aboveColor.G > backgroundThresholdG) ||
                                  (aboveColor.B > backgroundThresholdB))
                        {
                            // label current pixel, as the above
                            objectLabels[p] = objectLabels[p - imageWidth];
                        }

                        if ((aboveRightColor.R > backgroundThresholdR) ||
                             (aboveRightColor.G > backgroundThresholdG) ||
                             (aboveRightColor.B > backgroundThresholdB))
                        {
                            if (objectLabels[p] == 0)
                            {
                                // label current pixel, as the above right
                                objectLabels[p] = objectLabels[p + 1 - imageWidth];
                            }
                            else
                            {
                                int l1 = objectLabels[p];
                                int l2 = objectLabels[p + 1 - imageWidth];

                                if ((l1 != l2) && (map[l1] != map[l2]))
                                {
                                    // merge
                                    if (map[l1] == l1)
                                    {
                                        // map left value to the right
                                        map[l1] = map[l2];
                                    }
                                    else if (map[l2] == l2)
                                    {
                                        // map right value to the left
                                        map[l2] = map[l1];
                                    }
                                    else
                                    {
                                        // both values already mapped
                                        map[map[l1]] = map[l2];
                                        map[l1] = map[l2];
                                    }

                                    // reindex
                                    for (int i = 1; i <= labelsCount; i++)
                                    {
                                        if (map[i] != i)
                                        {
                                            // reindex
                                            int j = map[i];
                                            while (j != map[j])
                                            {
                                                j = map[j];
                                            }
                                            map[i] = j;
                                        }
                                    }
                                }
                            }
                        }

                        // label the object if it is not yet
                        if (objectLabels[p] == 0)
                        {
                            // create new label
                            objectLabels[p] = ++labelsCount;
                        }
                    }
                }

                // for the last pixel of the row, we need to check
                // only upper and upper-left pixels
                Color upperColor = ToColor(sourcePixelRegion.ImagePixels[pos]);
                if ((upperColor.R > backgroundThresholdR) ||
                     (upperColor.G > backgroundThresholdG) ||
                     (upperColor.B > backgroundThresholdB))
                {
                    Color upperLeftColor = ToColor(sourcePixelRegion.ImagePixels[pos - pixelSize]);
                    Color aboveLeftColor = ToColor(sourcePixelRegion.ImagePixels[pos - strideP1]);
                    Color aboveColor = ToColor(sourcePixelRegion.ImagePixels[pos - stride]);
                    // check surrounding pixels
                    if ((upperLeftColor.R > backgroundThresholdR) ||
                         (upperLeftColor.G > backgroundThresholdG) ||
                         (upperLeftColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the left
                        objectLabels[p] = objectLabels[p - 1];
                    }
                    else if ((aboveLeftColor.R > backgroundThresholdR) ||
                              (aboveLeftColor.G > backgroundThresholdG) ||
                              (aboveLeftColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the above left
                        objectLabels[p] = objectLabels[p - 1 - imageWidth];
                    }
                    else if ((aboveColor.R > backgroundThresholdR) ||
                              (aboveColor.G > backgroundThresholdG) ||
                              (aboveColor.B > backgroundThresholdB))
                    {
                        // label current pixel, as the above
                        objectLabels[p] = objectLabels[p - imageWidth];
                    }
                    else
                    {
                        // create new label
                        objectLabels[p] = ++labelsCount;
                    }
                }
                pos += pixelSize;
                ++p;
            }

            // allocate remapping array
            int[] reMap = new int[map.Length];

            // count objects and prepare remapping array
            objectsCount = 0;
            for (int i = 1; i <= labelsCount; i++)
            {
                if (map[i] == i)
                {
                    // increase objects count
                    reMap[i] = ++objectsCount;
                }
            }
            // second pass to complete remapping
            for (int i = 1; i <= labelsCount; i++)
            {
                if (map[i] != i)
                {
                    reMap[i] = reMap[map[i]];
                }
            }

            // repair object labels
            for (int i = 0, n = objectLabels.Length; i < n; i++)
            {
                objectLabels[i] = reMap[objectLabels[i]];
            }
        }
        protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
        {
            imageWidth = (int)sourcePixelRegion.Bounds.Width;
            imageHeight = (int)sourcePixelRegion.Bounds.Height;

            // do actual objects map building
            BuildObjectsMap(sourcePixelRegion);

            // collect information about blobs
            CollectObjectsInfo(sourcePixelRegion);

            // filter blobs by size if required
            if (filterBlobs)
            {
                // labels remapping array
                int[] labelsMap = new int[objectsCount + 1];

                for (int i = 1; i <= objectsCount; i++)
                {
                    labelsMap[i] = i;
                }

                // check dimension of all objects and filter them
                int objectsToRemove = 0;

                if (filter == null)
                {
                    for (int i = objectsCount - 1; i >= 0; i--)
                    {
                        int blobWidth = (int)blobs[i].Rectangle.Width;

                        int blobHeight = (int)blobs[i].Rectangle.Height;

                        if (coupledSizeFiltering == false)
                        {
                            // uncoupled filtering
                            if (
                                (blobWidth < minWidth) || (blobHeight < minHeight) ||
                                (blobWidth > maxWidth) || (blobHeight > maxHeight))
                            {
                                labelsMap[i + 1] = 0;

                                objectsToRemove++;
                                blobs.RemoveAt(i);
                            }
                        }
                        else
                        {
                            // coupled filtering
                            if (
                                ((blobWidth < minWidth) && (blobHeight < minHeight)) ||
                                ((blobWidth > maxWidth) && (blobHeight > maxHeight)))
                            {
                                labelsMap[i + 1] = 0;
                                objectsToRemove++;
                                blobs.RemoveAt(i);
                            }
                        }
                    }
                }
                else
                {
                    for (int i = objectsCount - 1; i >= 0; i--)
                    {
                        if (!filter.Check(blobs[i]))
                        {
                            labelsMap[i + 1] = 0;
                            objectsToRemove++;
                            blobs.RemoveAt(i);
                        }
                    }
                }

                // update labels remapping array
                int label = 0;
                for (int i = 1; i <= objectsCount; i++)
                {
                    if (labelsMap[i] != 0)
                    {
                        label++;
                        // update remapping array
                        labelsMap[i] = label;
                    }
                }

                // repair object labels
                for (int i = 0, n = objectLabels.Length; i < n; i++)
                {
                    objectLabels[i] = labelsMap[objectLabels[i]];
                }

                objectsCount -= objectsToRemove;

                // repair IDs
                for (int i = 0, n = blobs.Count; i < n; i++)
                {
                    blobs[i].ID = i + 1;
                }
            }

            // do we need to sort the list?
            if (objectsOrder != ObjectsOrder.None)
            {
                blobs.Sort(new BlobsSorter(objectsOrder));
            }

            if (HasPreview)
            {
                var rects = GetObjectsRectangles();
                Random rand = new Random();

                int count = 0;
                foreach (var rect in rects)
                {
                    DrawRectangle(sourcePixelRegion, rect, new Color() { A = 255, R = (byte)rand.Next(0, 255), G = (byte)rand.Next(0, 255), B = (byte)rand.Next(0, 255) });

                    count++;

                    if (count == PreviewCount)
                        break;
                }
            }
        }
        public void DrawLineBresenham(PixelRegion sourcePixelRegion, Point p1, Point p2, uint color)
        {
            int w = (int)sourcePixelRegion.ImageSize.Width;
            int h = (int)sourcePixelRegion.ImageSize.Height;
            var pixels = sourcePixelRegion.ImagePixels;

            int x1 = (int)p1.X;
            int y1 = (int)p1.Y;

            int x2 = (int)p2.X;
            int y2 = (int)p2.Y;

            // Distance start and end point
            int dx = x2 - x1;
            int dy = y2 - y1;

            // Determine sign for direction x
            int incx = 0;
            if (dx < 0)
            {
                dx = -dx;
                incx = -1;
            }
            else if (dx > 0)
            {
                incx = 1;
            }

            // Determine sign for direction y
            int incy = 0;
            if (dy < 0)
            {
                dy = -dy;
                incy = -1;
            }
            else if (dy > 0)
            {
                incy = 1;
            }

            // Which gradient is larger
            int pdx, pdy, odx, ody, es, el;
            if (dx > dy)
            {
                pdx = incx;
                pdy = 0;
                odx = incx;
                ody = incy;
                es = dy;
                el = dx;
            }
            else
            {
                pdx = 0;
                pdy = incy;
                odx = incx;
                ody = incy;
                es = dx;
                el = dy;
            }

            // Init start
            int x = x1;
            int y = y1;
            int error = el >> 1;
            if (y < h && y >= 0 && x < w && x >= 0)
            {
                pixels[y * w + x] = color;
            }

            // Walk the line!
            for (int i = 0; i < el; i++)
            {
                // Update error term
                error -= es;

                // Decide which coord to use
                if (error < 0)
                {
                    error += el;
                    x += odx;
                    y += ody;
                }
                else
                {
                    x += pdx;
                    y += pdy;
                }

                // Set pixel
                if (y < h && y >= 0 && x < w && x >= 0)
                {
                    pixels[y * w + x] = color;
                }
            }
        }
        private void DrawRectangle(PixelRegion sourcePixelRegion, Rect rectangle, Color color)
        {
            uint Color = FromColor(color);

            var topLeft = new Point(rectangle.X, rectangle.Y);
            var topRight = new Point(rectangle.X + rectangle.Width, rectangle.Y);
            var bottomLeft = new Point(rectangle.X, rectangle.Y + rectangle.Height);
            var bottomRight = new Point(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height);
            // draw line on the image
            DrawLineBresenham(sourcePixelRegion,
                topLeft,
                topRight,
                Color);

            DrawLineBresenham(sourcePixelRegion,
                topRight,
                bottomRight,
                Color);

            DrawLineBresenham(sourcePixelRegion,
                bottomRight,
                bottomLeft,
                Color);

            DrawLineBresenham(sourcePixelRegion,
                bottomLeft,
               topLeft,
                Color);
        }
            protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
            {
                SortedSet<uint> array = new SortedSet<uint>();

                //int width = Convert.ToInt32(sourcePixelRegion.ImageSize.Width);

                targetPixelRegion.ForEachRow((index, width, position) =>
                {
                for (int i = 0; i < width; i++)
                {
                var pixel = index + i;
                array.Clear();
                //var pixel = Convert.ToInt32(index + position.X + i);

                var pixelCentral = GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel, 0);
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel - width - 1, pixelCentral));
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel - width, pixelCentral));
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel - width + 1, pixelCentral));

                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel - 1, pixelCentral));
                array.Add(pixelCentral);
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel + 1, pixelCentral));

                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel + width - 1, pixelCentral));
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel + width, pixelCentral));
                array.Add(GetPixelOrDefault(sourcePixelRegion.ImagePixels, pixel + width + 1, pixelCentral));

                targetPixelRegion.ImagePixels[pixel] = array.ElementAt((array.Count- 1) /2);//.OrderBy(it => it).ToList()[4];
                }
                });
                //for (; pixel<sourcePixelRegion.ImagePixels.Length-width-2; pixel++)
                //{

                //for (int i=0; i< targetPixelRegion.ImagePixels.Length-1; i++)
                //{

                //    //targetPixelRegion.ImagePixels[i];
                //    //targetPixelRegion.ForEachRow((index, width, position) =>
                //    //{

                //    //    //Parallel.For(0, width, (i) =>
                //    //    for (int i = 0; i < width; i++)
                //    //    {

                //    //array.Clear();
                //    ////var pixel = index + i;
                //    //array.Add(sourcePixelRegion.ImagePixels[pixel - width - 1]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel - width]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel - width + 1]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel - 1]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel + 1]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel + width - 1]);
                //    //array.Add(sourcePixelRegion.ImagePixels[ pixel + width]);
                //    //array.Add(sourcePixelRegion.ImagePixels[pixel + width + 1]);

                //    targetPixelRegion.ImagePixels[pixel] = sourcePixelRegion.ImagePixels[pixel - 1];// GetPixelOrDefault(sourcePixelRegion, pixel);// array[4];
                //    }//  });
                    //for (int i = 0; i < width; ++i)
                    //{
                    //    //Almacenamos los pixels alrededor del actual en un array ordenado para coger la mediana
                    //    //var c = sourcePixelRegion.ImagePixels[index + i];
                    //    List<uint> array = new List<uint>();

                    //    var pixel = index + i;
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel - width - 1));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel - width));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel - width + 1));

                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel - 1));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel + 1));

                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel + width - 1));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel + width));
                    //    array.Add(GetPixelOrDefault(sourcePixelRegion, pixel + width + 1));

                    //    targetPixelRegion.ImagePixels[pixel] = array.OrderBy(it=>it).ToList()[4];
                    //}

                //});
            }
 protected override void OnProcess(PixelRegion sourcePixelRegion, PixelRegion targetPixelRegion)
 {
 }