Exemple #1
0
        public void CheckPassingOrTest()
        {
            // given: chain with filters
            var chain = new PixelFilterChain()
            {
                Mode = LogicMode.Or
            };

            var valueFilter1 = new Mock <IPixelValueFilter>(MockBehavior.Strict);

            valueFilter1.Setup(v => v.Check(It.IsAny <byte>())).Returns(false);
            var valueFilter2 = new Mock <IPixelValueFilter>(MockBehavior.Strict);

            valueFilter2.Setup(v => v.Check(It.IsAny <byte>())).Returns(false);
            var indexFilter1 = new Mock <IPixelIndexFilter>(MockBehavior.Strict);

            indexFilter1.Setup(i => i.Check(It.IsAny <int>())).Returns(false);
            var indexFilter2 = new Mock <IPixelIndexFilter>(MockBehavior.Strict);

            indexFilter2.Setup(i => i.Check(It.IsAny <int>())).Returns(true);

            chain.AddPixelFilter(valueFilter1.Object);
            chain.AddPixelFilter(valueFilter2.Object);
            chain.AddPixelFilter(indexFilter1.Object);
            chain.AddPixelFilter(indexFilter2.Object);

            // when: checking
            // then: passes
            Assert.That(chain.Check(0, 0), Is.True);
        }
Exemple #2
0
        public void CheckEmptyTest()
        {
            // given: empty chain
            var chain = new PixelFilterChain();

            // when: checking with empty chain
            // then: passes
            Assert.That(chain.Check(0, 0), Is.True);
        }
        /// <summary>
        /// Processes the given rgb <paramref name="img"/> in the
        /// given <paramref name="bounds"/> with
        /// the given <paramref name="processingFunc"/>.
        /// </summary>
        /// <param name="img">Image to process.</param>
        /// <param name="processingFunc">Processing function to process
        /// the <paramref name="img"/> with.</param>
        /// <param name="bounds">Bounds defining which pixels to process.</param>
        /// <param name="filterChain">Optional filter chain.</param>
        public static void ProcessRGB(Image img, Func <RGBPixel, RGBPixel> processingFunc, ProcessingBounds bounds, PixelFilterChain filterChain)
        {
            if (filterChain == null || !filterChain.HasActiveFilter)
            {
                ProcessRGB(img, processingFunc, bounds);
                return;
            }
            if (img == null)
            {
                throw new ArgumentNullException(nameof(img));
            }
            if (img.Planes.Count < 3)
            {
                throw new ArgumentException("Image is no rgb image", nameof(img));
            }
            if (processingFunc == null)
            {
                throw new ArgumentNullException(nameof(processingFunc));
            }

            if (img.Planes[0].TryGetLinearAccess(out LinearAccessData rData) &&
                img.Planes[1].TryGetLinearAccess(out LinearAccessData gData) &&
                img.Planes[2].TryGetLinearAccess(out LinearAccessData bData))
            {
                int startY  = bounds.StartY;
                int startX  = bounds.StartX;
                int boundsY = startY + bounds.Height;
                int boundsX = startX + bounds.Width;
                var rYInc   = (int)rData.YInc;
                var gYInc   = (int)gData.YInc;
                var bYInc   = (int)bData.YInc;
                var rXInc   = (int)rData.XInc;
                var gXInc   = (int)gData.XInc;
                var bXInc   = (int)bData.XInc;

                unsafe
                {
                    var pBaseR = (byte *)rData.BasePtr;
                    var pBaseG = (byte *)gData.BasePtr;
                    var pBaseB = (byte *)bData.BasePtr;

                    Parallel.For(startY, boundsY, (y) =>
                    {
                        byte *rLine = pBaseR + rYInc * y;
                        byte *gLine = pBaseG + gYInc * y;
                        byte *bLine = pBaseB + bYInc * y;

                        for (int x = startX; x < boundsX; x++)
                        {
                            byte *rPixel = rLine + rXInc * x;
                            byte *gPixel = gLine + gXInc * x;
                            byte *bPixel = bLine + bXInc * x;

                            if (filterChain.Check(*rPixel, *gPixel, *bPixel, y * boundsY + x))
                            {
                                var result = processingFunc.Invoke(new RGBPixel(*rPixel, *gPixel, *bPixel));
                                *rPixel    = result.R;
                                *gPixel    = result.G;
                                *bPixel    = result.B;
                            }
                        }
                    });
                }
            }
 /// <summary>
 /// Processes the given rgb <paramref name="img"/> with
 /// the given <paramref name="processingFunc"/>.
 /// </summary>
 /// <param name="img">Image to process.</param>
 /// <param name="processingFunc">Processing function to process
 /// the <paramref name="img"/> with.</param>
 /// <param name="filterChain">Optional filter chain.</param>
 public static void ProcessRGB(Image img, Func <RGBPixel, RGBPixel> processingFunc, PixelFilterChain filterChain)
 {
     if (filterChain == null || !filterChain.HasActiveFilter)
     {
         ProcessRGB(img, processingFunc);
     }
     else
     {
         ProcessRGB(img, processingFunc, new ProcessingBounds(img.Bounds), filterChain);
     }
 }
        /// <summary>
        /// Processes the pixels of the given <paramref name="plane"/>
        /// in the given <paramref name="bounds"/> with the
        /// given <paramref name="processorFunc"/>.
        /// </summary>
        /// <param name="plane">The plane whose pixels to process.</param>
        /// <param name="bounds">Bounds defining which pixels to process.</param>
        /// <param name="processorFunc">Func that takes a byte, processes
        /// it and returns a byte.</param>
        /// <param name="filterChain">Optional filter chain.</param>
        public static void ProcessMono(ImagePlane plane, ProcessingBounds bounds, Func <byte, byte> processorFunc, PixelFilterChain filterChain)
        {
            if (filterChain == null || !filterChain.HasActiveFilter)
            {
                ProcessMono(plane, bounds, processorFunc);
                return;
            }
            if (processorFunc == null)
            {
                throw new ArgumentNullException(nameof(processorFunc));
            }

            if (plane.TryGetLinearAccess(out LinearAccessData data))
            {
                var yInc    = (int)data.YInc;
                var xInc    = (int)data.XInc;
                int startY  = bounds.StartY;
                int startX  = bounds.StartX;
                int boundsY = startY + bounds.Height;
                int boundsX = startX + bounds.Width;
                unsafe
                {
                    var pBase = (byte *)data.BasePtr;

                    Parallel.For(startY, boundsY, (y) =>
                    {
                        byte *pLine = pBase + yInc * y;

                        for (int x = startX; x < boundsX; x++)
                        {
                            byte *pPixel = pLine + xInc * x;
                            if (filterChain.Check(*pPixel, y * boundsY + x))
                            {
                                *pPixel = processorFunc.Invoke(*pPixel);
                            }
                        }
                    });
                }
            }
            else
            {
                throw new ArgumentException("Plane could not be accessed linear", nameof(plane));
            }
        }
        public static ImagePlane ProcessMonoKernel(ImagePlane plane, Func <byte?[], byte> processingFunc, KernelSize kernel, ProcessingBounds bounds, PixelFilterChain filterChain)
        {
            if (filterChain == null || !filterChain.HasActiveFilter)
            {
                return(ProcessMonoKernel(plane, processingFunc, kernel, bounds));
            }

            if (plane.TryGetLinearAccess(out LinearAccessData data))
            {
                var newImage = Image.FromPlanes(MappingOption.CopyPixels, plane);
                var newData  = newImage.Planes[0].GetLinearAccess();
                var yInc     = (int)data.YInc;
                var xInc     = (int)data.XInc;
                var newYInc  = (int)newData.YInc;
                var newXInc  = (int)newData.XInc;

                int boundHeight = plane.Parent.Height - 1;
                int boundWidth  = plane.Parent.Width - 1;
                int startY      = bounds.StartY;
                int startX      = bounds.StartX;
                int boundsY     = startY + bounds.Height;
                int boundsX     = startX + bounds.Width;

                int kernelSize    = kernel.GetKernelNumber();
                int kernelArrSize = kernelSize * kernelSize;
                var kernelFac     = (int)System.Math.Floor(kernelSize / 2.0);

                unsafe
                {
                    var pBase    = (byte *)data.BasePtr;
                    var pBaseNew = (byte *)newData.BasePtr;

                    Parallel.For(startY, boundsY, (y) =>
                    {
                        var kernelValues = new byte?[kernelArrSize];
                        var pLine        = pBase + y * yInc;
                        int newLineInc   = newYInc * y;

                        for (int x = startX; x < boundsX; x++)
                        {
                            int kernelCounter = -1;
                            var pMiddle       = pLine + xInc * x;
                            for (int kRow = -kernelFac; kRow <= kernelFac; kRow++)
                            {
                                byte *pKLine = pMiddle + kRow * yInc;
                                int yKRow    = y + kRow;
                                for (int kColumn = -kernelFac; kColumn <= kernelFac; kColumn++)
                                {
                                    kernelCounter++;
                                    int xKColumn = x + kColumn;
                                    if (yKRow < 0 || yKRow > boundHeight || xKColumn < 0 || xKColumn > boundWidth)
                                    {
                                        continue;
                                    }

                                    byte *pPixel = pKLine + kColumn * xInc;
                                    if (filterChain.Check(*pPixel, y * boundsY + x))
                                    {
                                        kernelValues[kernelCounter] = *pPixel;
                                    }
                                }
                            }

                            if (kernelValues.Any(b => b.HasValue))
                            {
                                var pTargetLine  = pBaseNew + newLineInc;
                                var pTargetPixel = pTargetLine + newXInc * x; // current "middle pixel" in the target image
                                *pTargetPixel    = processingFunc.Invoke(kernelValues);
                            }
                        }
                    });
                }

                return(newImage.Planes[0]);
            }
            else
            {
                throw new ArgumentException("Plane could not be accessed linear", nameof(plane));
            }
        }
 public static ImagePlane ProcessMonoKernel(ImagePlane plane, Func <byte?[], byte> processingFunc, KernelSize kernel, PixelFilterChain filterChain)
 {
     if (filterChain == null || !filterChain.HasActiveFilter)
     {
         return(ProcessMonoKernel(plane, processingFunc, kernel));
     }
     else
     {
         return(ProcessMonoKernel(plane, processingFunc, kernel, new ProcessingBounds(plane.Parent.Bounds), filterChain));
     }
 }
 /// <summary>
 /// Processes the pixels of the given <paramref name="plane"/>
 /// with the given <paramref name="processorFunc"/>.
 /// </summary>
 /// <param name="plane">The plane whose pixels to process.</param>
 /// <param name="processorFunc">Func that takes a byte, processes
 /// it and returns a byte.</param>
 /// <param name="filterChain">Optional filter chain.</param>
 public static void ProcessMono(ImagePlane plane, Func <byte, byte> processorFunc, PixelFilterChain filterChain)
 {
     if (filterChain == null || !filterChain.HasActiveFilter)
     {
         ProcessMono(plane, processorFunc);
     }
     else
     {
         ProcessMono(plane, new ProcessingBounds(plane.Parent.Bounds), processorFunc, filterChain);
     }
 }