/// <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.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4;

            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;
            int offset  = image.Stride - rect.Width * pixelSize;

            // do the job
            byte* ptr = (byte*) image.ImageData.ToPointer( );
            byte t;

            // allign pointer to the first pixel to process
            ptr += ( startY * image.Stride + startX * pixelSize );

            // for each line
            for ( int y = startY; y < stopY; y++ )
            {
                // for each pixel
                for ( int x = startX; x < stopX; x++, ptr += pixelSize )
                {
                    // rotate colors of each pixel
                    t = ptr[RGB.R];
                    ptr[RGB.R] = ptr[RGB.G];
                    ptr[RGB.G] = ptr[RGB.B];
                    ptr[RGB.B] = t;
                }
                ptr += offset;
            }
        }
Example #2
0
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// 
        protected unsafe override void ProcessFilter(UnmanagedImage image)
        {
            int width = image.Width;
            int height = image.Height;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8;
            int stride = image.Stride;
            int offset = stride - image.Width * pixelSize;

            byte* src = (byte*)image.ImageData.ToPointer();

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++, src += pixelSize)
                {
                    double sum = src[RGB.R] + src[RGB.G] + src[RGB.B];
                    sum = sum == 0 ? 1 : sum;

                    double red = src[RGB.R] / sum;
                    double green = src[RGB.G] / sum;
                    double blue = 1 - red - green;

                    src[RGB.R] = (byte)(red * 255);
                    src[RGB.G] = (byte)(green * 255);
                    src[RGB.B] = (byte)(blue * 255);
                }
                src += offset;
            }
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData )
        {
            // get width and height
            int width = sourceData.Width;
            int height = sourceData.Height;

            int srcOffset = sourceData.Stride - width;
            int dstOffset = destinationData.Stride - width * 3;

            // do the job
            byte * src = (byte*) sourceData.ImageData.ToPointer( );
            byte * dst = (byte*) destinationData.ImageData.ToPointer( );

            // for each line
            for ( int y = 0; y < height; y++ )
            {
                // for each pixel
                for ( int x = 0; x < width; x++, src++, dst += 3 )
                {
                    dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = *src;
                }
                src += srcOffset;
                dst += dstOffset;
            }
        }
Example #4
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData )
        {
            // get source image size
            int width   = sourceData.Width;
            int height  = sourceData.Height;

            int pixelSize = Image.GetPixelFormatSize( sourceData.PixelFormat ) / 8;
            int srcStride = sourceData.Stride;
            int dstStride = destinationData.Stride;
            double xFactor = (double) width / newWidth;
            double yFactor = (double) height / newHeight;

            // do the job
            byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( );
            byte* baseDst = (byte*) destinationData.ImageData.ToPointer( );

            // for each line
            for ( int y = 0; y < newHeight; y++ )
            {
                byte* dst = baseDst + dstStride * y;
                byte* src = baseSrc + srcStride * ( (int) ( y * yFactor ) );
                byte* p;

                // for each pixel
                for ( int x = 0; x < newWidth; x++ )
                {
                    p = src + pixelSize * ( (int) ( x * xFactor ) );

                    for ( int i = 0; i < pixelSize; i++, dst++, p++ )
                    {
                        *dst = *p;
                    }
                }
            }
        }
Example #5
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
        {
            int pixelSize = ( ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ||
                              ( image.PixelFormat == PixelFormat.Format16bppGrayScale ) ) ? 1 : 3;

            int startY  = rect.Top;
            int stopY   = startY + rect.Height;

            int startX  = rect.Left * pixelSize;
            int stopX   = startX + rect.Width * pixelSize;

            byte* basePtr = (byte*) image.ImageData.ToPointer( );

            if (
                ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ||
                ( image.PixelFormat == PixelFormat.Format24bppRgb ) )
            {
                int offset = image.Stride - ( stopX - startX );

                // allign pointer to the first pixel to process
                byte* ptr = basePtr + ( startY * image.Stride + rect.Left * pixelSize );

                // invert
                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        // ivert each pixel
                        *ptr = (byte) ( 255 - *ptr );
                    }
                    ptr += offset;
                }
            }
            else
            {
                int stride = image.Stride;

                // allign pointer to the first pixel to process
                basePtr += ( startY * image.Stride + rect.Left * pixelSize * 2 );

                // invert
                for ( int y = startY; y < stopY; y++ )
                {
                    ushort* ptr = (ushort*) ( basePtr );

                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        // ivert each pixel
                        *ptr = (ushort) ( 65535 - *ptr );
                    }
                    basePtr += stride;
                }
            }
        }
Example #6
0
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // Lock the overlay image (left image)
            BitmapData overlayData = overlayImage.LockBits(
                new Rectangle(0, 0, overlayImage.Width, overlayImage.Height),
                ImageLockMode.ReadOnly, overlayImage.PixelFormat);

            int dstHeight = destinationData.Height;
            int src1Height = overlayData.Height;
            int src2Height = sourceData.Height;

            int src1Stride = overlayData.Stride;
            int src2Stride = sourceData.Stride;
            int dstStride = destinationData.Stride;

             int pixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
             int copySize1 = overlayData.Width * pixelSize;
             int copySize2 = sourceData.Width * pixelSize;

            // do the job
            unsafe
            {
                byte* src1 = (byte*)overlayData.Scan0.ToPointer();
                byte* src2 = (byte*)sourceData.ImageData.ToPointer();
                byte* dst = (byte*)destinationData.ImageData.ToPointer();

                // for each line
                for (int y = 0; y < dstHeight; y++)
                {
                    if (y < src1Height)
                        Accord.SystemTools.CopyUnmanagedMemory(dst, src1, copySize1);
                    if (y < src2Height)
                        Accord.SystemTools.CopyUnmanagedMemory(dst + copySize1, src2, copySize2);
                    
                    src1 += src1Stride;
                    src2 += src2Stride;
                    dst += dstStride;
                }
            }

            // Release
            overlayImage.UnlockBits(overlayData);
        }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Morph"/> class.
 /// </summary>
 /// 
 /// <param name="unmanagedOverlayImage">Unmanaged overlay image.</param>
 /// 
 public Morph( UnmanagedImage unmanagedOverlayImage )
     : base( unmanagedOverlayImage )
 {
     InitFormatTranslations( );
 }
Example #8
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        ///
        protected override unsafe void ProcessFilter( UnmanagedImage image )
        {
            int width  = image.Width;
            int height = image.Height;

            // 1 - invert the source image
            Invert invertFilter = new Invert( );
            UnmanagedImage invertedImage = invertFilter.Apply( image );

            // 2 - use blob counter to find holes (they are white objects now on the inverted image)
            BlobCounter blobCounter = new BlobCounter( );
            blobCounter.ProcessImage( invertedImage );
            Blob[] blobs = blobCounter.GetObjectsInformation( );

            // 3 - check all blobs and determine which should be filtered
            byte[] newObjectColors = new byte[blobs.Length + 1];
            newObjectColors[0] = 255; // don't touch the objects, which have 0 ID

            for ( int i = 0, n = blobs.Length; i < n; i++ )
            {
                Blob blob = blobs[i];

                if ( ( blob.Rectangle.Left == 0 ) || ( blob.Rectangle.Top == 0 ) ||
                     ( blob.Rectangle.Right == width ) || ( blob.Rectangle.Bottom == height ) )
                {
                    newObjectColors[blob.ID] = 0;
                }
                else
                {
                    if ( ( ( coupledSizeFiltering ) && ( blob.Rectangle.Width <= maxHoleWidth ) && ( blob.Rectangle.Height <= maxHoleHeight ) ) |
                         ( ( !coupledSizeFiltering ) && ( ( blob.Rectangle.Width <= maxHoleWidth ) || ( blob.Rectangle.Height <= maxHoleHeight ) ) ) )
                    {
                        newObjectColors[blob.ID] = 255;
                    }
                    else
                    {
                        newObjectColors[blob.ID] = 0;
                    }
                }
            }

            // 4 - process the source image image and fill holes
            byte* ptr = (byte*) image.ImageData.ToPointer( );
            int offset = image.Stride - width;

            int[] objectLabels = blobCounter.ObjectLabels;

            for ( int y = 0, i = 0; y < height; y++ )
            {
                for ( int x = 0; x < width; x++, i++, ptr++ )
                {
                    *ptr = newObjectColors[objectLabels[i]];
                }
                ptr += offset;
            }
        }
Example #9
0
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get width and height
            int width  = sourceData.Width;
            int height = sourceData.Height;

            if (SaveColorChannels && SaveLumChannel)
            {
                LRGBArrays = new LRGBArrays(new ushort[width * height], new ushort[width * height], new ushort[width * height], new ushort[width * height]);
            }
            else if (!SaveColorChannels && SaveLumChannel)
            {
                LRGBArrays = new LRGBArrays(new ushort[width * height], new ushort[0], new ushort[0], new ushort[0]);
            }
            else if (SaveColorChannels && !SaveLumChannel)
            {
                LRGBArrays = new LRGBArrays(new ushort[0], new ushort[width * height], new ushort[width * height], new ushort[width * height]);
            }

            int widthM1  = width - 1;
            int heightM1 = height - 1;

            int srcStride = sourceData.Stride / 2;

            int srcOffset = (srcStride - width) / 2;
            int dstOffset = (destinationData.Stride - width * 6) / 6;

            // do the job
            ushort *src = (ushort *)sourceData.ImageData.ToPointer();
            ushort *dst = (ushort *)destinationData.ImageData.ToPointer();

            int[] rgbValues   = new int[3];
            int[] rgbCounters = new int[3];

            if (!PerformDemosaicing)
            {
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, src++, dst += 3)
                    {
                        dst[RGB.R] = dst[RGB.G] = dst[RGB.B] = 0;
                        dst[BayerPattern[y & 1, x & 1]] = *src;
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                int counter = 0;
                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < width; x++, src++, dst += 3)
                    {
                        rgbValues[0]   = rgbValues[1] = rgbValues[2] = 0;
                        rgbCounters[0] = rgbCounters[1] = rgbCounters[2] = 0;

                        int bayerIndex = BayerPattern[y & 1, x & 1];

                        rgbValues[bayerIndex] += *src;
                        rgbCounters[bayerIndex]++;

                        if (x != 0)
                        {
                            bayerIndex = BayerPattern[y & 1, (x - 1) & 1];

                            rgbValues[bayerIndex] += src[-1];
                            rgbCounters[bayerIndex]++;
                        }

                        if (x != widthM1)
                        {
                            bayerIndex = BayerPattern[y & 1, (x + 1) & 1];

                            rgbValues[bayerIndex] += src[1];
                            rgbCounters[bayerIndex]++;
                        }

                        if (y != 0)
                        {
                            bayerIndex = BayerPattern[(y - 1) & 1, x & 1];

                            rgbValues[bayerIndex] += src[-srcStride];
                            rgbCounters[bayerIndex]++;

                            if (x != 0)
                            {
                                bayerIndex = BayerPattern[(y - 1) & 1, (x - 1) & 1];

                                rgbValues[bayerIndex] += src[-srcStride - 1];
                                rgbCounters[bayerIndex]++;
                            }

                            if (x != widthM1)
                            {
                                bayerIndex = BayerPattern[(y - 1) & 1, (x + 1) & 1];

                                rgbValues[bayerIndex] += src[-srcStride + 1];
                                rgbCounters[bayerIndex]++;
                            }
                        }

                        if (y != heightM1)
                        {
                            bayerIndex = BayerPattern[(y + 1) & 1, x & 1];

                            rgbValues[bayerIndex] += src[srcStride];
                            rgbCounters[bayerIndex]++;

                            if (x != 0)
                            {
                                bayerIndex = BayerPattern[(y + 1) & 1, (x - 1) & 1];

                                rgbValues[bayerIndex] += src[srcStride - 1];
                                rgbCounters[bayerIndex]++;
                            }

                            if (x != widthM1)
                            {
                                bayerIndex             = BayerPattern[(y + 1) & 1, (x + 1) & 1];
                                rgbValues[bayerIndex] += src[srcStride + 1];
                                rgbCounters[bayerIndex]++;
                            }
                        }
                        dst[RGB.R] = (ushort)(rgbValues[RGB.R] / rgbCounters[RGB.R]);
                        dst[RGB.G] = (ushort)(rgbValues[RGB.G] / rgbCounters[RGB.G]);
                        dst[RGB.B] = (ushort)(rgbValues[RGB.B] / rgbCounters[RGB.B]);
                        if (SaveColorChannels)
                        {
                            LRGBArrays.Red[counter]   = dst[RGB.R];
                            LRGBArrays.Green[counter] = dst[RGB.G];
                            LRGBArrays.Blue[counter]  = dst[RGB.B];
                        }
                        if (SaveLumChannel)
                        {
                            LRGBArrays.Lum[counter] = (ushort)Math.Floor((dst[RGB.R] + dst[RGB.G] + dst[RGB.B]) / 3d);
                        }
                        counter++;
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
        }
 /// <summary>
 /// Apply filter to an image (not implemented).
 /// </summary>
 /// 
 /// <param name="image">Image in unmanaged memory.</param>
 /// 
 /// <returns>Returns filter's result obtained by applying the filter to
 /// the source image.</returns>
 /// 
 /// <exception cref="NotImplementedException">The method is not implemented.</exception>
 /// 
 public UnmanagedImage Apply( UnmanagedImage image )
 {
     throw new NotImplementedException( "The method is not implemented for the filter." );
 }
Example #11
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
        {
            // calculate threshold for the given image
            thresholdFilter.ThresholdValue = CalculateThreshold( image, rect );

            // thresholding
            thresholdFilter.ApplyInPlace( image, rect );
        }
Example #12
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage source, UnmanagedImage destination )
        {
            int pixelSize = Image.GetPixelFormatSize( source.PixelFormat ) / 8;

            // image width and height
            int width  = source.Width;
            int height = source.Height;

            int widthToProcess  = System.Math.Min( width,  warpMap.GetLength( 1 ) );
            int heightToProcess = System.Math.Min( height, warpMap.GetLength( 0 ) );

            int srcStride = source.Stride;
            int dstStride = destination.Stride;
            int dstOffset = dstStride - widthToProcess * pixelSize;

            // new pixel's position
            int ox, oy;

            byte* src = (byte*) source.ImageData.ToPointer( );
            byte* dst = (byte*) destination.ImageData.ToPointer( );
            byte* p;

            // for each line
            for ( int y = 0; y < heightToProcess; y++ )
            {
                // for each pixel
                for ( int x = 0; x < widthToProcess; x++ )
                {
                    // get original pixel's coordinates
                    ox = x + warpMap[y, x].X;
                    oy = y + warpMap[y, x].Y;

                    // check if the random pixel is inside of image
                    if ( ( ox >= 0 ) && ( oy >= 0 ) && ( ox < width ) && ( oy < height ) )
                    {
                        p = src + oy * srcStride + ox * pixelSize;

                        for ( int i = 0; i < pixelSize; i++, dst++, p++ )
                        {
                            *dst = *p;
                        }
                    }
                    else
                    {
                        for ( int i = 0; i < pixelSize; i++, dst++ )
                        {
                            *dst = 0;
                        }
                    }
                }

                // copy remaining pixel in the row
                if ( width != widthToProcess )
                {
                    AForge.SystemTools.CopyUnmanagedMemory( dst, src + y * srcStride + widthToProcess * pixelSize, ( width - widthToProcess ) * pixelSize );
                }

                dst += dstOffset;
            }

            // copy remaining rows of pixels
            for ( int y = heightToProcess; y < height; y++, dst += dstStride )
            {
                AForge.SystemTools.CopyUnmanagedMemory( dst, src + y * srcStride, width * pixelSize );
            }
        }
        /// <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 startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;
            int offset  = image.Stride - rect.Width;

            // value which is caried from pixel to pixel
            short carry = 0;

            // do the job
            byte* ptr = (byte*) image.ImageData.ToPointer( );

            // allign pointer to the first pixel to process
            ptr += ( startY * image.Stride + startX );

            // for each line	
            for ( int y = startY; y < stopY; y++ )
            {
                carry = 0;

                // for each pixel
                for ( int x = startX; x < stopX; x++, ptr++ )
                {
                    carry += *ptr;

                    if ( carry >= threshold )
                    {
                        *ptr = (byte) 255;
                        carry -= 255;
                    }
                    else
                    {
                        *ptr = (byte) 0;
                    }
                }
                ptr += offset;
            }
        }
Example #14
0
        // Process the filter on the image with 16 bits per color channel
        private unsafe void ProcessFilter16bpc(UnmanagedImage image)
        {
            int  pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8;
            bool is64bpp   = (pixelSize == 8);

            // pad fill colours to 16-bits
            ushort fillRed   = (ushort)(this.fillRed << 8);
            ushort fillGreen = (ushort)(this.fillGreen << 8);
            ushort fillBlue  = (ushort)(this.fillBlue << 8);
            ushort fillAlpha = (ushort)(this.fillAlpha << 8);

            // get image width and height
            int width  = image.Width;
            int height = image.Height;
            int stride = image.Stride;

            int movePointX = movePoint.X;
            int movePointY = movePoint.Y;

            // intersection rectangle
            Rectangle intersect = Rectangle.Intersect(
                new Rectangle(0, 0, width, height),
                new Rectangle(movePointX, movePointY, width, height));

            // start, stop and step for X and Y
            int yStart = 0;
            int yStop  = height;
            int yStep  = 1;
            int xStart = 0;
            int xStop  = width;
            int xStep  = 1;

            if (movePointY > 0)
            {
                yStart = height - 1;
                yStop  = -1;
                yStep  = -1;
            }
            if (movePointX > 0)
            {
                xStart = width - 1;
                xStop  = -1;
                xStep  = -1;
            }

            // do the job
            byte *  src = (byte *)image.ImageData.ToPointer( );
            ushort *pixel, moved;

            if (image.PixelFormat == PixelFormat.Format16bppGrayScale)
            {
                // grayscale image
                for (int y = yStart; y != yStop; y += yStep)
                {
                    for (int x = xStart; x != xStop; x += xStep)
                    {
                        // current pixel
                        pixel = (ushort *)(src + y * stride + x * 2);

                        if (intersect.Contains(x, y))
                        {
                            moved = (ushort *)(src + (y - movePointY) * stride + (x - movePointX) * 2);
                            *pixel = *moved;
                        }
                        else
                        {
                            *pixel = fillGray;
                        }
                    }
                }
            }
            else
            {
                // color image
                for (int y = yStart; y != yStop; y += yStep)
                {
                    for (int x = xStart; x != xStop; x += xStep)
                    {
                        // current pixel
                        pixel = (ushort *)(src + y * stride + x * pixelSize);

                        if (intersect.Contains(x, y))
                        {
                            moved = (ushort *)(src + (y - movePointY) * stride + (x - movePointX) * pixelSize);

                            pixel[RGB.R] = moved[RGB.R];
                            pixel[RGB.G] = moved[RGB.G];
                            pixel[RGB.B] = moved[RGB.B];

                            if (is64bpp)
                            {
                                pixel[RGB.A] = moved[RGB.A];
                            }
                        }
                        else
                        {
                            pixel[RGB.R] = fillRed;
                            pixel[RGB.G] = fillGreen;
                            pixel[RGB.B] = fillBlue;

                            if (is64bpp)
                            {
                                pixel[RGB.A] = fillAlpha;
                            }
                        }
                    }
                }
            }
        }
Example #15
0
 /// <summary>
 /// Apply filter to an image (not implemented).
 /// </summary>
 ///
 /// <param name="image">Image in unmanaged memory.</param>
 ///
 /// <returns>Returns filter's result obtained by applying the filter to
 /// the source image.</returns>
 ///
 /// <exception cref="NotImplementedException">The method is not implemented.</exception>
 ///
 public UnmanagedImage Apply(UnmanagedImage image)
 {
     throw new NotImplementedException("The method is not implemented for the filter.");
 }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get source image size
            int    width      = sourceData.Width;
            int    height     = sourceData.Height;
            double oldXradius = (double)(width - 1) / 2;
            double oldYradius = (double)(height - 1) / 2;

            // get destination image size
            int    newWidth   = destinationData.Width;
            int    newHeight  = destinationData.Height;
            double newXradius = (double)(newWidth - 1) / 2;
            double newYradius = (double)(newHeight - 1) / 2;

            // angle's sine and cosine
            double angleRad = -angle * Math.PI / 180;
            double angleCos = Math.Cos(angleRad);
            double angleSin = Math.Sin(angleRad);

            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride -
                            ((destinationData.PixelFormat == PixelFormat.Format8bppIndexed) ? newWidth : newWidth * 3);

            // fill values
            byte fillR = fillColor.R;
            byte fillG = fillColor.G;
            byte fillB = fillColor.B;

            // do the job
            byte *src = (byte *)sourceData.ImageData.ToPointer( );
            byte *dst = (byte *)destinationData.ImageData.ToPointer( );

            // destination pixel's coordinate relative to image center
            double cx, cy;
            // coordinates of source points
            double ox, oy, tx, ty, dx1, dy1, dx2, dy2;
            int    ox1, oy1, ox2, oy2;
            // width and height decreased by 1
            int ymax = height - 1;
            int xmax = width - 1;
            // temporary pointers
            byte *p1, p2, p3, p4;

            // check pixel format
            if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // grayscale
                cy = -newYradius;
                for (int y = 0; y < newHeight; y++)
                {
                    // do some pre-calculations of source points' coordinates
                    // (calculate the part which depends on y-loop, but does not
                    // depend on x-loop)
                    tx = angleSin * cy + oldXradius;
                    ty = angleCos * cy + oldYradius;

                    cx = -newXradius;
                    for (int x = 0; x < newWidth; x++, dst++)
                    {
                        // coordinates of source point
                        ox = tx + angleCos * cx;
                        oy = ty - angleSin * cx;

                        // top-left coordinate
                        ox1 = (int)ox;
                        oy1 = (int)oy;

                        // validate source pixel's coordinates
                        if ((ox1 < 0) || (oy1 < 0) || (ox1 >= width) || (oy1 >= height))
                        {
                            // fill destination image with filler
                            *dst = fillG;
                        }
                        else
                        {
                            // bottom-right coordinate
                            ox2 = (ox1 == xmax) ? ox1 : ox1 + 1;
                            oy2 = (oy1 == ymax) ? oy1 : oy1 + 1;

                            if ((dx1 = ox - (double)ox1) < 0)
                            {
                                dx1 = 0;
                            }
                            dx2 = 1.0 - dx1;

                            if ((dy1 = oy - (double)oy1) < 0)
                            {
                                dy1 = 0;
                            }
                            dy2 = 1.0 - dy1;

                            p1 = src + oy1 * srcStride;
                            p2 = src + oy2 * srcStride;

                            // interpolate using 4 points
                            *dst = (byte)(
                                dy2 * (dx2 * p1[ox1] + dx1 * p1[ox2]) +
                                dy1 * (dx2 * p2[ox1] + dx1 * p2[ox2]));
                        }
                        cx++;
                    }
                    cy++;
                    dst += dstOffset;
                }
            }
            else
            {
                // RGB
                cy = -newYradius;
                for (int y = 0; y < newHeight; y++)
                {
                    // do some pre-calculations of source points' coordinates
                    // (calculate the part which depends on y-loop, but does not
                    // depend on x-loop)
                    tx = angleSin * cy + oldXradius;
                    ty = angleCos * cy + oldYradius;

                    cx = -newXradius;
                    for (int x = 0; x < newWidth; x++, dst += 3)
                    {
                        // coordinates of source point
                        ox = tx + angleCos * cx;
                        oy = ty - angleSin * cx;

                        // top-left coordinate
                        ox1 = (int)ox;
                        oy1 = (int)oy;

                        // validate source pixel's coordinates
                        if ((ox1 < 0) || (oy1 < 0) || (ox1 >= width) || (oy1 >= height))
                        {
                            // fill destination image with filler
                            dst[RGB.R] = fillR;
                            dst[RGB.G] = fillG;
                            dst[RGB.B] = fillB;
                        }
                        else
                        {
                            // bottom-right coordinate
                            ox2 = (ox1 == xmax) ? ox1 : ox1 + 1;
                            oy2 = (oy1 == ymax) ? oy1 : oy1 + 1;

                            if ((dx1 = ox - (float)ox1) < 0)
                            {
                                dx1 = 0;
                            }
                            dx2 = 1.0f - dx1;

                            if ((dy1 = oy - (float)oy1) < 0)
                            {
                                dy1 = 0;
                            }
                            dy2 = 1.0f - dy1;

                            // get four points
                            p1  = p2 = src + oy1 * srcStride;
                            p1 += ox1 * 3;
                            p2 += ox2 * 3;

                            p3  = p4 = src + oy2 * srcStride;
                            p3 += ox1 * 3;
                            p4 += ox2 * 3;

                            // interpolate using 4 points

                            // red
                            dst[RGB.R] = (byte)(
                                dy2 * (dx2 * p1[RGB.R] + dx1 * p2[RGB.R]) +
                                dy1 * (dx2 * p3[RGB.R] + dx1 * p4[RGB.R]));

                            // green
                            dst[RGB.G] = (byte)(
                                dy2 * (dx2 * p1[RGB.G] + dx1 * p2[RGB.G]) +
                                dy1 * (dx2 * p3[RGB.G] + dx1 * p4[RGB.G]));

                            // blue
                            dst[RGB.B] = (byte)(
                                dy2 * (dx2 * p1[RGB.B] + dx1 * p2[RGB.B]) +
                                dy1 * (dx2 * p3[RGB.B] + dx1 * p4[RGB.B]));
                        }
                        cx++;
                    }
                    cy++;
                    dst += dstOffset;
                }
            }
        }
Example #17
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect)
        {
            // get pixel size
            int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;

            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = startX + rect.Width;
            int stopY  = startY + rect.Height;
            int offset = image.Stride - rect.Width * pixelSize;

            RGB rgb = new RGB( );
            HSL hsl = new HSL( );

            bool updated;

            // do the job
            byte *ptr = (byte *)image.ImageData.ToPointer( );

            // allign pointer to the first pixel to process
            ptr += (startY * image.Stride + startX * pixelSize);

            // for each row
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, ptr += pixelSize)
                {
                    updated   = false;
                    rgb.Red   = ptr[RGB.R];
                    rgb.Green = ptr[RGB.G];
                    rgb.Blue  = ptr[RGB.B];

                    // convert to HSL
                    AForge.Imaging.HSL.FromRGB(rgb, hsl);

                    // check HSL values
                    if (
                        (hsl.Saturation >= saturation.Min) && (hsl.Saturation <= saturation.Max) &&
                        (hsl.Luminance >= luminance.Min) && (hsl.Luminance <= luminance.Max) &&
                        (
                            ((hue.Min < hue.Max) && (hsl.Hue >= hue.Min) && (hsl.Hue <= hue.Max)) ||
                            ((hue.Min > hue.Max) && ((hsl.Hue >= hue.Min) || (hsl.Hue <= hue.Max)))
                        )
                        )
                    {
                        if (!fillOutsideRange)
                        {
                            if (updateH)
                            {
                                hsl.Hue = fillH;
                            }
                            if (updateS)
                            {
                                hsl.Saturation = fillS;
                            }
                            if (updateL)
                            {
                                hsl.Luminance = fillL;
                            }

                            updated = true;
                        }
                    }
                    else
                    {
                        if (fillOutsideRange)
                        {
                            if (updateH)
                            {
                                hsl.Hue = fillH;
                            }
                            if (updateS)
                            {
                                hsl.Saturation = fillS;
                            }
                            if (updateL)
                            {
                                hsl.Luminance = fillL;
                            }

                            updated = true;
                        }
                    }

                    if (updated)
                    {
                        // convert back to RGB
                        AForge.Imaging.HSL.ToRGB(hsl, rgb);

                        ptr[RGB.R] = rgb.Red;
                        ptr[RGB.G] = rgb.Green;
                        ptr[RGB.B] = rgb.Blue;
                    }
                }
                ptr += offset;
            }
        }
Example #18
0
        protected unsafe override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            PixelFormat pixelFormat = image.PixelFormat;
            int         width       = image.Width;
            int         height      = image.Height;
            int         num;

            switch (pixelFormat)
            {
            case PixelFormat.Format24bppRgb:
            case PixelFormat.Format32bppRgb:
            case PixelFormat.Format8bppIndexed:
            case PixelFormat.Format32bppArgb:
            {
                int num2;
                switch (pixelFormat)
                {
                default:
                    num2 = 4;
                    break;

                case PixelFormat.Format24bppRgb:
                    num2 = 3;
                    break;

                case PixelFormat.Format8bppIndexed:
                    num2 = 1;
                    break;
                }
                int   num3 = num2;
                int   num4 = width * num3;
                int   num5 = image.Stride - num4;
                int   num6 = overlay.Stride - num4;
                byte *ptr  = (byte *)image.ImageData.ToPointer();
                byte *ptr2 = (byte *)overlay.ImageData.ToPointer();
                for (int i = 0; i < height; i++)
                {
                    int num7 = 0;
                    while (num7 < num4)
                    {
                        if (*ptr2 < *ptr)
                        {
                            *ptr = *ptr2;
                        }
                        num7++;
                        ptr++;
                        ptr2++;
                    }
                    ptr  += num5;
                    ptr2 += num6;
                }
                return;
            }

            default:
                num = 4;
                break;

            case PixelFormat.Format48bppRgb:
                num = 3;
                break;

            case PixelFormat.Format16bppGrayScale:
                num = 1;
                break;
            }
            int   num8    = num;
            int   num9    = width * num8;
            int   stride  = image.Stride;
            int   stride2 = overlay.Stride;
            byte *ptr3    = (byte *)image.ImageData.ToPointer();
            byte *ptr4    = (byte *)overlay.ImageData.ToPointer();

            for (int j = 0; j < height; j++)
            {
                ushort *ptr5  = (ushort *)(ptr3 + (long)j * (long)stride);
                ushort *ptr6  = (ushort *)(ptr4 + (long)j * (long)stride2);
                int     num10 = 0;
                while (num10 < num9)
                {
                    if (*ptr6 < *ptr5)
                    {
                        *ptr5 = *ptr6;
                    }
                    num10++;
                    ptr5++;
                    ptr6++;
                }
            }
        }
Example #19
0
        protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
        {
            if (rect.Width < 3 || rect.Height < 3)
            {
                throw new InvalidImagePropertiesException("Processing rectangle mast be at least 3x3 in size.");
            }
            int   num     = rect.Left + 1;
            int   num2    = rect.Top + 1;
            int   num3    = rect.Right - 1;
            int   num4    = rect.Bottom - 1;
            int   stride  = destinationData.Stride;
            int   stride2 = sourceData.Stride;
            int   num5    = stride - rect.Width + 1;
            int   num6    = stride2 - rect.Width + 1;
            byte *ptr     = (byte *)sourceData.ImageData.ToPointer();
            byte *ptr2    = (byte *)destinationData.ImageData.ToPointer();

            ptr  += num - 1 + (num2 - 1) * stride2;
            ptr2 += num - 1 + (num2 - 1) * stride;
            byte b = *ptr;

            if (ptr[1] > b)
            {
                b = ptr[1];
            }
            if (ptr[stride2] > b)
            {
                b = ptr[stride2];
            }
            if (ptr[stride2 + 1] > b)
            {
                b = ptr[stride2 + 1];
            }
            *ptr2 = b;
            ptr++;
            ptr2++;
            int num7 = num;

            while (num7 < num3)
            {
                b = *ptr;
                if (ptr[-1] > b)
                {
                    b = ptr[-1];
                }
                if (ptr[1] > b)
                {
                    b = ptr[1];
                }
                if (ptr[stride2 - 1] > b)
                {
                    b = ptr[stride2 - 1];
                }
                if (ptr[stride2] > b)
                {
                    b = ptr[stride2];
                }
                if (ptr[stride2 + 1] > b)
                {
                    b = ptr[stride2 + 1];
                }
                *ptr2 = b;
                num7++;
                ptr++;
                ptr2++;
            }
            b = *ptr;
            if (ptr[-1] > b)
            {
                b = ptr[-1];
            }
            if (ptr[stride2 - 1] > b)
            {
                b = ptr[stride2 - 1];
            }
            if (ptr[stride2] > b)
            {
                b = ptr[stride2];
            }
            *ptr2 = b;
            ptr  += num6;
            ptr2 += num5;
            for (int i = num2; i < num4; i++)
            {
                b = *ptr;
                if (ptr[1] > b)
                {
                    b = ptr[1];
                }
                if (ptr[-stride2] > b)
                {
                    b = ptr[-stride2];
                }
                if (ptr[-stride2 + 1] > b)
                {
                    b = ptr[-stride2 + 1];
                }
                if (ptr[stride2] > b)
                {
                    b = ptr[stride2];
                }
                if (ptr[stride2 + 1] > b)
                {
                    b = ptr[stride2 + 1];
                }
                *ptr2 = b;
                ptr++;
                ptr2++;
                int num8 = num;
                while (num8 < num3)
                {
                    b = *ptr;
                    if (ptr[-1] > b)
                    {
                        b = ptr[-1];
                    }
                    if (ptr[1] > b)
                    {
                        b = ptr[1];
                    }
                    if (ptr[-stride2 - 1] > b)
                    {
                        b = ptr[-stride2 - 1];
                    }
                    if (ptr[-stride2] > b)
                    {
                        b = ptr[-stride2];
                    }
                    if (ptr[-stride2 + 1] > b)
                    {
                        b = ptr[-stride2 + 1];
                    }
                    if (ptr[stride2 - 1] > b)
                    {
                        b = ptr[stride2 - 1];
                    }
                    if (ptr[stride2] > b)
                    {
                        b = ptr[stride2];
                    }
                    if (ptr[stride2 + 1] > b)
                    {
                        b = ptr[stride2 + 1];
                    }
                    *ptr2 = b;
                    num8++;
                    ptr++;
                    ptr2++;
                }
                b = *ptr;
                if (ptr[-1] > b)
                {
                    b = ptr[-1];
                }
                if (ptr[-stride2 - 1] > b)
                {
                    b = ptr[-stride2 - 1];
                }
                if (ptr[-stride2] > b)
                {
                    b = ptr[-stride2];
                }
                if (ptr[stride2 - 1] > b)
                {
                    b = ptr[stride2 - 1];
                }
                if (ptr[stride2] > b)
                {
                    b = ptr[stride2];
                }
                *ptr2 = b;
                ptr  += num6;
                ptr2 += num5;
            }
            *ptr2 = (byte)(*ptr | ptr[1] | ptr[-stride2] | ptr[-stride2 + 1]);
            b = *ptr;
            if (ptr[1] > b)
            {
                b = ptr[1];
            }
            if (ptr[-stride2] > b)
            {
                b = ptr[-stride2];
            }
            if (ptr[-stride2 + 1] > b)
            {
                b = ptr[-stride2 + 1];
            }
            *ptr2 = b;
            ptr++;
            ptr2++;
            int num9 = num;

            while (num9 < num3)
            {
                b = *ptr;
                if (ptr[-1] > b)
                {
                    b = ptr[-1];
                }
                if (ptr[1] > b)
                {
                    b = ptr[1];
                }
                if (ptr[-stride2 - 1] > b)
                {
                    b = ptr[-stride2 - 1];
                }
                if (ptr[-stride2] > b)
                {
                    b = ptr[-stride2];
                }
                if (ptr[-stride2 + 1] > b)
                {
                    b = ptr[-stride2 + 1];
                }
                *ptr2 = b;
                num9++;
                ptr++;
                ptr2++;
            }
            b = *ptr;
            if (ptr[-1] > b)
            {
                b = ptr[-1];
            }
            if (ptr[-stride2 - 1] > b)
            {
                b = ptr[-stride2 - 1];
            }
            if (ptr[-stride2] > b)
            {
                b = ptr[-stride2];
            }
            *ptr2 = b;
        }
Example #20
0
 /// <summary>
 /// Apply filter to an unmanaged image or its part.
 /// </summary>
 ///
 /// <param name="image">Unmanaged image to apply filter to.</param>
 /// <param name="rect">Image rectangle for processing by the filter.</param>
 ///
 /// <remarks>The method applies the filter directly to the provided source image.</remarks>
 ///
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 ///
 public void ApplyInPlace(UnmanagedImage image, Rectangle rect)
 {
     dilation.ApplyInPlace(image, rect);
     errosion.ApplyInPlace(image, rect);
 }
Example #21
0
 /// <summary>
 /// Apply filter to an image in unmanaged memory.
 /// </summary>
 /// 
 /// <param name="sourceImage">Source image in unmanaged memory to apply filter to.</param>
 /// <param name="destinationImage">Destination image in unmanaged memory to put result into.</param>
 /// 
 /// <remarks><para>The method keeps the source image unchanged and puts result of image processing
 /// into destination image.</para>
 /// 
 /// <para><note>The destination image must have the same width and height as source image. Also
 /// destination image must have pixel format, which is expected by particular filter (see
 /// <see cref="FormatTranslations"/> property for information about pixel format conversions).</note></para>
 /// </remarks>
 /// 
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 /// <exception cref="InvalidImagePropertiesException">Incorrect destination pixel format.</exception>
 /// <exception cref="InvalidImagePropertiesException">Destination image has wrong width and/or height.</exception>
 ///
 public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage )
 {
     errosion.Apply( sourceImage, destinationImage );
     dilatation.ApplyInPlace( destinationImage );
 }
Example #22
0
 /// <summary>
 /// Apply filter to an image (not implemented).
 /// </summary>
 ///
 /// <param name="sourceImage">Source image to be processed.</param>
 /// <param name="destinationImage">Destination image to store filter's result.</param>
 ///
 /// <exception cref="NotImplementedException">The method is not implemented.</exception>
 ///
 public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
 {
     throw new NotImplementedException("The method is not implemented filter.");
 }
Example #23
0
 /// <summary>
 /// Apply filter to an unmanaged image or its part.
 /// </summary>
 /// 
 /// <param name="image">Unmanaged image to apply filter to.</param>
 /// <param name="rect">Image rectangle for processing by the filter.</param>
 /// 
 /// <remarks>The method applies the filter directly to the provided source image.</remarks>
 /// 
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 /// 
 public void ApplyInPlace( UnmanagedImage image, Rectangle rect )
 {
     errosion.ApplyInPlace( image, rect );
     dilatation.ApplyInPlace( image, rect );
 }
Example #24
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            PixelFormat pixelFormat = image.PixelFormat;
            // get image dimension
            int width  = image.Width;
            int height = image.Height;
            // pixel value
            int v;

            if (
                (pixelFormat == PixelFormat.Format8bppIndexed) ||
                (pixelFormat == PixelFormat.Format24bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppArgb))
            {
                // initialize other variables
                int pixelSize = (pixelFormat == PixelFormat.Format8bppIndexed) ? 1 :
                                (pixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                int lineSize  = width * pixelSize;
                int srcOffset = image.Stride - lineSize;
                int ovrOffset = overlay.Stride - lineSize;

                // do the job
                byte *ptr = (byte *)image.ImageData.ToPointer( );
                byte *ovr = (byte *)overlay.ImageData.ToPointer( );

                // for each line
                for (int y = 0; y < height; y++)
                {
                    // for each pixel
                    for (int x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        // abs(sub)
                        v = (int)*ptr - (int)*ovr;
                        *ptr = (v < 0) ? (byte)-v : (byte)v;
                    }
                    ptr += srcOffset;
                    ovr += ovrOffset;
                }
            }
            else
            {
                // initialize other variables
                int pixelSize = (pixelFormat == PixelFormat.Format16bppGrayScale) ? 1 :
                                (pixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4;
                int lineSize  = width * pixelSize;
                int srcStride = image.Stride;
                int ovrStride = overlay.Stride;

                // do the job
                byte *basePtr = (byte *)image.ImageData.ToPointer( );
                byte *baseOvr = (byte *)overlay.ImageData.ToPointer( );

                // for each line
                for (int y = 0; y < height; y++)
                {
                    ushort *ptr = (ushort *)(basePtr + y * srcStride);
                    ushort *ovr = (ushort *)(baseOvr + y * ovrStride);

                    // for each pixel
                    for (int x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        // abs(sub)
                        v = (int)*ptr - (int)*ovr;
                        *ptr = (v < 0) ? (ushort)-v : (ushort)v;
                    }
                }
            }
        }
        // Perform parallel image processing without checking pixels' coordinates to make sure those are in bounds
        private unsafe void ProcessWithoutChecksParallel( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
        {
            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = rect.Right;
            int stopY  = rect.Bottom;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize( source.PixelFormat ) / 8;
            int kernelHalf = kernelSize / 2;
            int bytesInKernelRow = kernelSize * pixelSize;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;

            int srcOffset = srcStride - rect.Width * pixelSize;
            int dstOffset = dstStride - rect.Width * pixelSize;

            // offset of the first kernel's pixel
            int srcKernelFistPixelOffset = kernelHalf * ( srcStride + pixelSize );
            // offset to move to the next kernel's pixel after processing one kernel's row
            int srcKernelOffset = srcStride - bytesInKernelRow;

            byte* srcBase = (byte*) source.ImageData.ToPointer( );
            byte* dstBase = (byte*) destination.ImageData.ToPointer( );

            // allign pointers to the left most pixel in the first row
            srcBase += startX * pixelSize;
            dstBase += startX * pixelSize;

            if ( pixelSize > 1 )
            {
                Parallel.For( startY, stopY, delegate( int y )
                {
                    byte* src = srcBase + y * srcStride;
                    byte* dst = dstBase + y * dstStride;

                    byte srcR, srcG, srcB;
                    byte srcR0, srcG0, srcB0;
                    byte* srcPixel;

                    int tx, ty;

                    double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB;

                    for ( int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefR = 0;
                        sCoefG = 0;
                        sCoefB = 0;
                        sMembR = 0;
                        sMembG = 0;
                        sMembB = 0;

                        srcR0 = src[RGB.R];
                        srcG0 = src[RGB.G];
                        srcB0 = src[RGB.B];

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;

                                srcR = srcPixel[RGB.R];
                                srcG = srcPixel[RGB.G];
                                srcB = srcPixel[RGB.B];

                                coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0];
                                coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0];
                                coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0];

                                sCoefR += coefR;
                                sCoefG += coefG;
                                sCoefB += coefB;

                                sMembR += coefR * srcR;
                                sMembG += coefG * srcG;
                                sMembB += coefB * srcB;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        dst[RGB.R] = (byte) ( sMembR / sCoefR );
                        dst[RGB.G] = (byte) ( sMembG / sCoefG );
                        dst[RGB.B] = (byte) ( sMembB / sCoefB );
                    }
                } );
            }
            else
            {
                // 8bpp grayscale images
                Parallel.For( startY, stopY, delegate( int y )
                {
                    byte* src = srcBase + y * srcStride;
                    byte* dst = dstBase + y * dstStride;

                    byte srcC;
                    byte srcC0;
                    byte* srcPixel;
                    double sCoefC, sMembC, coefC;

                    int tx, ty;

                    for ( int x = startX; x < stopX; x++, src++, dst++ )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefC = 0;
                        sMembC = 0;

                        srcC0 = *src;

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;

                                srcC = *( srcPixel );
                                coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0];

                                sCoefC += coefC;
                                sMembC += coefC * srcC;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        *dst = (byte) ( sMembC / sCoefC );
                    }
                } );
            }
        }
Example #26
0
        /// <summary>
        ///   Computes the new image size.
        /// </summary>
        ///
        protected override Size CalculateNewImageSize(UnmanagedImage sourceData)
        {
            // Calculate source size
            float w = sourceData.Width;
            float h = sourceData.Height;

            // Get the four corners and the center of the image
            PointF[] corners =
            {
                new PointF(0,      0),
                new PointF(w,      0),
                new PointF(0,      h),
                new PointF(w,      h),
                new PointF(w / 2f, h / 2f)
            };

            // Project those points
            corners = homography.Inverse().TransformPoints(corners);

            // Recalculate image size
            float[] px = { corners[0].X, corners[1].X, corners[2].X, corners[3].X };
            float[] py = { corners[0].Y, corners[1].Y, corners[2].Y, corners[3].Y };

            float maxX     = Matrix.Max(px);
            float minX     = Matrix.Min(px);
            float newWidth = Math.Max(maxX, overlayImage.Width) - Math.Min(0, minX);

            float maxY      = Accord.Math.Matrix.Max(py);
            float minY      = Accord.Math.Matrix.Min(py);
            float newHeight = Math.Max(maxY, overlayImage.Height) - Math.Min(0, minY);


            // Store overlay image size
            this.imageSize = new Size((int)Math.Round(maxX - minX), (int)Math.Round(maxY - minY));

            // Store image center
            this.center = Point.Round(corners[4]);

            // Calculate and store image offset
            int offsetX = 0, offsetY = 0;

            if (minX < 0)
            {
                offsetX = (int)Math.Round(minX);
            }
            if (minY < 0)
            {
                offsetY = (int)Math.Round(minY);
            }

            this.offset = new Point(offsetX, offsetY);

            if (Double.IsNaN(newWidth) || newWidth == 0)
            {
                newWidth = 1;
            }

            if (Double.IsNaN(newHeight) || newHeight == 0)
            {
                newHeight = 1;
            }

            // Return the final image size
            return(new Size((int)Math.Ceiling(newWidth), (int)Math.Ceiling(newHeight)));
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// 
        protected override void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData )
        {
            // get width and height
            int width  = sourceData.Width;
            int height = sourceData.Height;

            if ( ( ( width & 1 ) == 1 ) || ( ( height & 1 ) == 1 ) ||
                 ( width < 2 ) || ( height < 2 ) )
            {
                throw new InvalidImagePropertiesException( "Source image must have even width and height. Width and height can not be smaller than 2." );
            }

            switch ( bayerPattern )
            {
                case BayerPattern.GRBG:
                    ApplyGRBG( sourceData, destinationData );
                    break;

                case BayerPattern.BGGR:
                    ApplyBGGR( sourceData, destinationData );
                    break;
            }
        }
Example #28
0
        /// <summary>
        ///   Process the image filter.
        /// </summary>
        ///
        protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // Locks the overlay image
            BitmapData overlayData = overlayImage.LockBits(
                new Rectangle(0, 0, overlayImage.Width, overlayImage.Height),
                ImageLockMode.ReadOnly, overlayImage.PixelFormat);


            // get source image size
            int width  = sourceData.Width;
            int height = sourceData.Height;

            // get destination image size
            int newWidth  = destinationData.Width;
            int newHeight = destinationData.Height;

            int srcPixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
            int orgPixelSize = System.Drawing.Image.GetPixelFormatSize(overlayData.PixelFormat) / 8;

            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride - newWidth * 4; // destination always 32bpp argb


            // Get center of first image
            Point center1 = new Point((int)(overlayImage.Width / 2f),
                                      (int)(overlayImage.Height / 2f));

            // Get center of second image
            Point center2 = this.center;



            // Compute maximum center distances
            float dmax1 = Math.Min(
                distance(center1.X, center1.Y, center2.X - imageSize.Width / 2f, center1.Y),
                distance(center1.X, center1.Y, center1.X, center1.Y + overlayImage.Height / 2f));

            float dmax2 = Math.Min(
                distance(center2.X, center2.Y, center2.X + imageSize.Width / 2f, center2.Y),
                distance(center2.X, center2.Y, center2.X, center2.Y + imageSize.Height / 2f));

            float dmax = -System.Math.Abs(dmax2 - dmax1);


            // fill values
            byte fillR = fillColor.R;
            byte fillG = fillColor.G;
            byte fillB = fillColor.B;
            byte fillA = 0;//fillColor.A;

            // Retrieve homography matrix as float array
            float[,] H = (float[, ])homography;


            // do the job
            unsafe
            {
                byte *org = (byte *)overlayData.Scan0.ToPointer();
                byte *src = (byte *)sourceData.ImageData.ToPointer();
                byte *dst = (byte *)destinationData.ImageData.ToPointer();

                // destination pixel's coordinate relative to image center
                double cx, cy;

                // destination pixel's homogenous coordinate
                double hx, hy, hw;

                // source pixel's coordinates
                int ox, oy;



                // Copy the overlay image
                for (int y = 0; y < newHeight; y++)
                {
                    for (int x = 0; x < newWidth; x++, dst += 4)
                    {
                        ox = (int)(x + offset.X);
                        oy = (int)(y + offset.Y);

                        // validate source pixel's coordinates
                        if ((ox < 0) || (oy < 0) || (ox >= overlayData.Width) || (oy >= overlayData.Height))
                        {
                            // fill destination image with filler
                            dst[0] = fillB;
                            dst[1] = fillG;
                            dst[2] = fillR;
                            dst[3] = fillA;
                        }
                        else
                        {
                            int c = oy * overlayData.Stride + ox * orgPixelSize;

                            // fill destination image with pixel from original image

                            if (orgPixelSize == 3)
                            {
                                // 24 bpp
                                dst[0] = org[c + 0];
                                dst[1] = org[c + 1];
                                dst[2] = org[c + 2];
                                dst[3] = (byte)255;
                            }
                            else if (orgPixelSize == 4)
                            {
                                // 32 bpp
                                dst[0] = org[c + 0];
                                dst[1] = org[c + 1];
                                dst[2] = org[c + 2];
                                dst[3] = org[c + 3];
                            }
                            else
                            {
                                // 8 bpp
                                dst[0] = org[c];
                                dst[1] = org[c];
                                dst[2] = org[c];
                                dst[3] = org[c];
                            }
                        }
                    }
                    dst += dstOffset;
                }

                org = (byte *)overlayData.Scan0.ToPointer();
                src = (byte *)sourceData.ImageData.ToPointer();
                dst = (byte *)destinationData.ImageData.ToPointer();

                // Project and blend the second image
                for (int y = 0; y < newHeight; y++)
                {
                    for (int x = 0; x < newWidth; x++, dst += 4)
                    {
                        cx = x + offset.X;
                        cy = y + offset.Y;

                        // projection using homogenous coordinates
                        hw = (H[2, 0] * cx + H[2, 1] * cy + H[2, 2]);
                        hx = (H[0, 0] * cx + H[0, 1] * cy + H[0, 2]) / hw;
                        hy = (H[1, 0] * cx + H[1, 1] * cy + H[1, 2]) / hw;

                        // coordinate of the nearest point
                        ox = (int)(hx);
                        oy = (int)(hy);

                        // validate source pixel's coordinates
                        if ((ox >= 0) && (oy >= 0) && (ox < width) && (oy < height))
                        {
                            int c = oy * srcStride + ox * srcPixelSize;

                            // fill destination image with pixel from source image
                            if (srcPixelSize == 4 && src[c + 3] == 0)
                            {
                                // source pixel is fully transparent, nothing to copy
                            }
                            else if (dst[3] > 0)
                            {
                                float f1 = 0.5f, f2 = 0.5f;

                                if (Gradient)
                                {
                                    // there is a pixel from the other image here, blend
                                    float d1 = distance(x, y, center1.X, center1.Y);
                                    float d2 = distance(x, y, center2.X, center2.Y);
                                    f1 = Accord.Math.Tools.Scale(0, dmax, 0, 1, d1 - d2);

                                    if (f1 < 0)
                                    {
                                        f1 = 0f;
                                    }
                                    if (f1 > 1)
                                    {
                                        f1 = 1f;
                                    }
                                    f2 = (1f - f1);
                                }

                                if (!AlphaOnly)
                                {
                                    if (srcPixelSize == 3)
                                    {
                                        // 24 bpp
                                        dst[0] = (byte)(src[c + 0] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c + 1] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c + 2] * f2 + dst[2] * f1);
                                        dst[3] = (byte)255;
                                    }
                                    else if (srcPixelSize == 4)
                                    {
                                        // 32 bpp
                                        dst[0] = (byte)(src[c + 0] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c + 1] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c + 2] * f2 + dst[2] * f1);
                                        dst[3] = (byte)(src[c + 3] * f2 + dst[3] * f1);
                                    }
                                    else
                                    {
                                        // 8 bpp
                                        dst[0] = (byte)(src[c] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c] * f2 + dst[2] * f1);
                                        dst[3] = (byte)255;
                                    }
                                }
                                else
                                {
                                    if (srcPixelSize == 3)
                                    {
                                        // 24 bpp
                                        dst[0] = (byte)(src[c + 0]);
                                        dst[1] = (byte)(src[c + 1]);
                                        dst[2] = (byte)(src[c + 2]);
                                    }
                                    else if (srcPixelSize == 4)
                                    {
                                        // 32 bpp
                                        dst[0] = (byte)(src[c + 0]);
                                        dst[1] = (byte)(src[c + 1]);
                                        dst[2] = (byte)(src[c + 2]);
                                    }
                                    else
                                    {
                                        // 8 bpp
                                        dst[0] = (byte)(src[c]);
                                        dst[1] = (byte)(src[c]);
                                        dst[2] = (byte)(src[c]);
                                    }
                                }
                            }
                            else
                            {
                                // just copy the source into the destination image

                                if (srcPixelSize == 3)
                                {
                                    // 24bpp
                                    dst[0] = src[c + 0];
                                    dst[1] = src[c + 1];
                                    dst[2] = src[c + 2];
                                    dst[3] = (byte)255;
                                }
                                else if (srcPixelSize == 4)
                                {
                                    // 32bpp
                                    dst[0] = src[c + 0];
                                    dst[1] = src[c + 1];
                                    dst[2] = src[c + 2];
                                    dst[3] = src[c + 3];
                                }
                                else
                                {
                                    // 8bpp
                                    dst[0] = src[c];
                                    dst[1] = src[c];
                                    dst[2] = src[c];
                                    dst[3] = 0;
                                }
                            }
                        }
                    }
                    dst += dstOffset;
                }
            }

            overlayImage.UnlockBits(overlayData);
        }
Example #29
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
        {
            // get pixel size
            int pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4;

            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;
            int offset  = image.Stride - rect.Width * pixelSize;

            RGB rgb = new RGB( );
            HSL hsl = new HSL( );

            bool updated;

            // do the job
            byte* ptr = (byte*) image.ImageData.ToPointer( );

            // allign pointer to the first pixel to process
            ptr += ( startY * image.Stride + startX * pixelSize );

            // for each row
            for ( int y = startY; y < stopY; y++ )
            {
                // for each pixel
                for ( int x = startX; x < stopX; x++, ptr += pixelSize )
                {
                    updated   = false;
                    rgb.Red   = ptr[RGB.R];
                    rgb.Green = ptr[RGB.G];
                    rgb.Blue  = ptr[RGB.B];

                    // convert to HSL
                    AForge.Imaging.HSL.FromRGB( rgb, hsl );

                    // check HSL values
                    if (
                        ( hsl.Saturation >= saturation.Min ) && ( hsl.Saturation <= saturation.Max ) &&
                        ( hsl.Luminance >= luminance.Min ) && ( hsl.Luminance <= luminance.Max ) &&
                        (
                        ( ( hue.Min < hue.Max ) && ( hsl.Hue >= hue.Min ) && ( hsl.Hue <= hue.Max ) ) ||
                        ( ( hue.Min > hue.Max ) && ( ( hsl.Hue >= hue.Min ) || ( hsl.Hue <= hue.Max ) ) )
                        )
                        )
                    {
                        if ( !fillOutsideRange )
                        {
                            if ( updateH ) hsl.Hue = fillH;
                            if ( updateS ) hsl.Saturation = fillS;
                            if ( updateL ) hsl.Luminance = fillL;

                            updated = true;
                        }
                    }
                    else
                    {
                        if ( fillOutsideRange )
                        {
                            if ( updateH ) hsl.Hue = fillH;
                            if ( updateS ) hsl.Saturation = fillS;
                            if ( updateL ) hsl.Luminance = fillL;

                            updated = true;
                        }
                    }

                    if ( updated )
                    {
                        // convert back to RGB
                        AForge.Imaging.HSL.ToRGB( hsl, rgb );

                        ptr[RGB.R] = rgb.Red;
                        ptr[RGB.G] = rgb.Green;
                        ptr[RGB.B] = rgb.Blue;
                    }
                }
                ptr += offset;
            }
        }
Example #30
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Divide"/> class.
 /// </summary>
 ///
 /// <param name="unmanagedOverlayImage">Unmanaged overlay image.</param>
 ///
 public Divide(UnmanagedImage unmanagedOverlayImage)
     : base(unmanagedOverlayImage)
 {
     InitFormatTranslations();
 }
Example #31
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
        {
            int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8;

            // processing start and stop X,Y positions
            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;
            int offset  = image.Stride - rect.Width * pixelSize;

            // do the job
            byte* ptr = (byte*) image.ImageData.ToPointer( );

            // allign pointer to the first pixel to process
            ptr += ( startY * image.Stride + startX * pixelSize );

            if ( image.PixelFormat == PixelFormat.Format8bppIndexed )
            {
                // grayscale image
                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        // gray
                        *ptr = mapGreen[*ptr];
                    }
                    ptr += offset;
                }
            }
            else
            {
                // RGB image
                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, ptr += pixelSize )
                    {
                        // red
                        ptr[RGB.R] = mapRed[ptr[RGB.R]];
                        // green
                        ptr[RGB.G] = mapGreen[ptr[RGB.G]];
                        // blue
                        ptr[RGB.B] = mapBlue[ptr[RGB.B]];
                    }
                    ptr += offset;
                }
            }
        }
Example #32
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            PixelFormat pixelFormat = image.PixelFormat;
            int         width       = image.Width;
            int         height      = image.Height;

            if ((pixelFormat == PixelFormat.Format8bppIndexed) ||
                (pixelFormat == PixelFormat.Format24bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppArgb))
            {
                // initialize other variables
                var pixelSize = (pixelFormat == PixelFormat.Format8bppIndexed) ? 1 :
                                (pixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                var lineSize  = width * pixelSize;
                var srcOffset = image.Stride - lineSize;
                var ovrOffset = overlay.Stride - lineSize;
                // new pixel value

                // do the job
                var ptr = (byte *)image.ImageData.ToPointer();
                var ovr = (byte *)overlay.ImageData.ToPointer();

                // for each line
                for (var y = 0; y < height; y++)
                {
                    // for each pixel
                    for (var x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        var v   = (*ptr * 256f) / (*ovr + 1f);
                        *   ptr = (v > 255) ? (byte)255 : (byte)v;
                    }
                    ptr += srcOffset;
                    ovr += ovrOffset;
                }
            }
            else
            {
                // initialize other variables
                var pixelSize = (pixelFormat == PixelFormat.Format16bppGrayScale) ? 1 :
                                (pixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4;
                var lineSize  = width * pixelSize;
                var srcStride = image.Stride;
                var ovrStride = overlay.Stride;
                // new pixel value

                // do the job
                var basePtr = (byte *)image.ImageData.ToPointer();
                var baseOvr = (byte *)overlay.ImageData.ToPointer();

                // for each line
                for (var y = 0; y < height; y++)
                {
                    var ptr = (ushort *)(basePtr + y * srcStride);
                    var ovr = (ushort *)(baseOvr + y * ovrStride);

                    // for each pixel
                    for (var x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        var v   = (*ptr * 65536f) / (*ovr + 1f);
                        *   ptr = (v > 65535) ? (ushort)65535 : (ushort)v;
                    }
                }
            }
        }
Example #33
0
 /// <summary>
 /// Apply filter to an unmanaged image.
 /// </summary>
 ///
 /// <param name="image">Unmanaged image to apply filter to.</param>
 ///
 /// <remarks>The method applies the filter directly to the provided source unmanaged image.</remarks>
 ///
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 ///
 public void ApplyInPlace(UnmanagedImage image)
 {
     dilation.ApplyInPlace(image);
     errosion.ApplyInPlace(image);
 }
Example #34
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            var pixelFormat = image.PixelFormat;
            // get image dimension
            var width  = image.Width;
            var height = image.Height;

            if (
                (pixelFormat == PixelFormat.Format8bppIndexed) ||
                (pixelFormat == PixelFormat.Format24bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppRgb) ||
                (pixelFormat == PixelFormat.Format32bppArgb))
            {
                // initialize other variables
                var pixelSize = (pixelFormat == PixelFormat.Format8bppIndexed) ? 1 :
                                (pixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
                var lineSize  = width * pixelSize;
                var srcOffset = image.Stride - lineSize;
                var ovrOffset = overlay.Stride - lineSize;

                // do the job
                var ptr = (byte *)image.ImageData.ToPointer( );
                var ovr = (byte *)overlay.ImageData.ToPointer( );

                // for each line
                for (var y = 0; y < height; y++)
                {
                    // for each pixel
                    for (var x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        if (*ovr < *ptr)
                        {
                            *ptr = *ovr;
                        }
                    }
                    ptr += srcOffset;
                    ovr += ovrOffset;
                }
            }
            else
            {
                // initialize other variables
                var pixelSize = (pixelFormat == PixelFormat.Format16bppGrayScale) ? 1 :
                                (pixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4;
                var lineSize  = width * pixelSize;
                var srcStride = image.Stride;
                var ovrStride = overlay.Stride;

                // do the job
                var basePtr = (byte *)image.ImageData.ToPointer( );
                var baseOvr = (byte *)overlay.ImageData.ToPointer( );

                // for each line
                for (var y = 0; y < height; y++)
                {
                    var ptr = (ushort *)(basePtr + y * srcStride);
                    var ovr = (ushort *)(baseOvr + y * ovrStride);

                    // for each pixel
                    for (var x = 0; x < lineSize; x++, ptr++, ovr++)
                    {
                        if (*ovr < *ptr)
                        {
                            *ptr = *ovr;
                        }
                    }
                }
            }
        }
Example #35
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override unsafe void ProcessFilter( UnmanagedImage image, UnmanagedImage overlay )
        {
            // get image dimension
            int width  = image.Width;
            int height = image.Height;

            // initialize other variables
            int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3;
            int lineSize  = width * pixelSize;
            int offset    = image.Stride - lineSize;
            int ovrOffset = overlay.Stride - lineSize;
            // percentage of overlay image
            double q = 1.0 - sourcePercent;

            // do the job
            byte * ptr = (byte*) image.ImageData.ToPointer( );
            byte * ovr = (byte*) overlay.ImageData.ToPointer( );

            // for each line
            for ( int y = 0; y < height; y++ )
            {
                // for each pixel
                for ( int x = 0; x < lineSize; x++, ptr++, ovr++ )
                {
                    *ptr = (byte) ( ( sourcePercent * ( *ptr ) ) + ( q * ( *ovr ) ) );
                }
                ptr += offset;
                ovr += ovrOffset;
            }
        }
Example #36
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Intersect"/> class.
 /// </summary>
 ///
 /// <param name="unmanagedOverlayImage">Unmanaged overlay image.</param>
 ///
 public Intersect(UnmanagedImage unmanagedOverlayImage)
     : base(unmanagedOverlayImage)
 {
     this.InitFormatTranslations( );
 }
Example #37
0
        /// <summary>
        /// Apply filter to an image in unmanaged memory.
        /// </summary>
        /// 
        /// <param name="image">Source image in unmanaged memory to apply filter to.</param>
        /// 
        /// <returns>Returns filter's result obtained by applying the filter to
        /// the source image.</returns>
        /// 
        /// <remarks>The method keeps the source image unchanged and returns
        /// the result of image processing filter as new image.</remarks>
        /// 
        /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
        ///
        public UnmanagedImage Apply( UnmanagedImage image )
        {
            UnmanagedImage destImage = errosion.Apply( image );
            dilatation.ApplyInPlace( destImage );

            return destImage;
        }
Example #38
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        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);
        }
Example #39
0
 /// <summary>
 /// Apply filter to an unmanaged image.
 /// </summary>
 /// 
 /// <param name="image">Unmanaged image to apply filter to.</param>
 /// 
 /// <remarks>The method applies the filter directly to the provided source unmanaged image.</remarks>
 /// 
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 ///
 public void ApplyInPlace( UnmanagedImage image )
 {
     errosion.ApplyInPlace( image );
     dilatation.ApplyInPlace( image );
 }
        /// <summary>
        /// Perform color dithering for the specified image.
        /// </summary>
        ///
        /// <param name="sourceImage">Source image to do color dithering for.</param>
        ///
        /// <returns>Returns color dithered image. See <see cref="ColorTable"/> for information about format of
        /// the result image.</returns>
        ///
        /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image. It must 24 or 32 bpp color image.</exception>
        ///
        public Bitmap Apply(UnmanagedImage sourceImage)
        {
            if ((sourceImage.PixelFormat != PixelFormat.Format24bppRgb) &&
                (sourceImage.PixelFormat != PixelFormat.Format32bppRgb) &&
                (sourceImage.PixelFormat != PixelFormat.Format32bppArgb) &&
                (sourceImage.PixelFormat != PixelFormat.Format32bppPArgb))
            {
                throw new UnsupportedImageFormatException("Unsupported pixel format of the source image.");
            }

            cache.Clear();

            // get image size
            int width     = sourceImage.Width;
            int height    = sourceImage.Height;
            int stride    = sourceImage.Stride;
            int pixelSize = Bitmap.GetPixelFormatSize(sourceImage.PixelFormat) / 8;


            // create destination image
            Bitmap destImage = new Bitmap(width, height, (colorTable.Length > 16) ?
                                          PixelFormat.Format8bppIndexed : PixelFormat.Format4bppIndexed);
            // and init its palette
            ColorPalette cp = destImage.Palette;

            for (int i = 0, n = colorTable.Length; i < n; i++)
            {
                cp.Entries[i] = colorTable[i];
            }
            destImage.Palette = cp;

            // lock destination image
            BitmapData destData = destImage.LockBits(new Rectangle(0, 0, width, height),
                                                     ImageLockMode.ReadWrite, destImage.PixelFormat);

            // pixel values
            int r, g, b, toAdd;
            int rows = matrix.GetLength(0);
            int cols = matrix.GetLength(1);


            // do the job
            unsafe
            {
                byte *ptr     = (byte *)sourceImage.ImageData.ToPointer();
                byte *dstBase = (byte *)destData.Scan0.ToPointer();
                byte  colorIndex;

                bool is8bpp = (colorTable.Length > 16);

                // for each line
                for (int y = 0; y < height; y++)
                {
                    byte *dst = dstBase + y * destData.Stride;

                    // for each pixels
                    for (int x = 0; x < width; x++, ptr += pixelSize)
                    {
                        toAdd = matrix[(y % rows), (x % cols)];
                        r     = ptr[RGB.R] + toAdd;
                        g     = ptr[RGB.G] + toAdd;
                        b     = ptr[RGB.B] + toAdd;

                        if (r > 255)
                        {
                            r = 255;
                        }
                        if (g > 255)
                        {
                            g = 255;
                        }
                        if (b > 255)
                        {
                            b = 255;
                        }

                        // get color from palette, which is the closest to current pixel's value
                        GetClosestColor(r, g, b, out colorIndex);

                        // write color index as pixel's value to destination image
                        if (is8bpp)
                        {
                            *dst = colorIndex;
                            dst++;
                        }
                        else
                        {
                            if (x % 2 == 0)
                            {
                                *dst |= (byte)(colorIndex << 4);
                            }
                            else
                            {
                                *dst |= (colorIndex);
                                dst++;
                            }
                        }
                    }
                }
            }

            destImage.UnlockBits(destData);

            return(destImage);
        }
Example #41
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        /// 
        /// <exception cref="InvalidImagePropertiesException">Processing rectangle mast be at least 3x3 in size.</exception>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect )
        {
            if ( ( rect.Width < 3 ) || ( rect.Height < 3 ) )
            {
                throw new InvalidImagePropertiesException( "Processing rectangle mast be at least 3x3 in size." );
            }

            // processing start and stop X,Y positions
            int startX  = rect.Left + 1;
            int startY  = rect.Top + 1;
            int stopX   = rect.Right - 1;
            int stopY   = rect.Bottom - 1;

            int dstStride = destinationData.Stride;
            int srcStride = sourceData.Stride;

            int dstOffset = dstStride - rect.Width + 1;
            int srcOffset = srcStride - rect.Width + 1;

            // image pointers
            byte* src = (byte*) sourceData.ImageData.ToPointer( );
            byte* dst = (byte*) destinationData.ImageData.ToPointer( );

            // allign pointers by X and Y
            src += ( startX - 1 ) + ( startY - 1 ) * srcStride;
            dst += ( startX - 1 ) + ( startY - 1 ) * dstStride;

            // --- process the first line setting all to black
            for ( int x = startX - 1; x < stopX; x++, src++, dst++ )
            {
                *dst = 0;
            }
            *dst = 0;

            src += srcOffset;
            dst += dstOffset;

            // --- process all lines except the last one
            for ( int y = startY; y < stopY; y++ )
            {
                // set edge pixel to black
                *dst = 0;

                src++;
                dst++;

                // for each pixel
                for ( int x = startX; x < stopX; x++, src++, dst++ )
                {
                    *dst = (byte) ( *src & src[-1] & src[1] &
                        src[-srcStride] & src[-srcStride - 1] & src[-srcStride + 1] &
                        src[srcStride] & src[srcStride - 1] & src[srcStride + 1] );
                }

                // set edge pixel to black
                *dst = 0;

                src += srcOffset;
                dst += dstOffset;
            }

            // --- process the last line setting all to black

            // for each pixel
            for ( int x = startX - 1; x < stopX; x++, src++, dst++ )
            {
                *dst = 0;
            }
            *dst = 0;
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
        {
            // processing start and stop X,Y positions
            int startX = rect.Left + 1;
            int startY = rect.Top + 1;
            int stopX  = startX + rect.Width - 2;
            int stopY  = startY + rect.Height - 2;

            int width  = rect.Width - 2;
            int height = rect.Height - 2;

            int dstStride = destination.Stride;
            int srcStride = source.Stride;

            int dstOffset = dstStride - rect.Width + 2;
            int srcOffset = srcStride - rect.Width + 2;

            // pixel's value and gradients
            int gx, gy;
            //
            double orientation, toAngle = 180.0 / System.Math.PI;
            float  leftPixel = 0, rightPixel = 0;

            // STEP 1 - blur image
            UnmanagedImage blurredImage = gaussianFilter.Apply(source);

            // orientation array
            byte[] orients = new byte[width * height];
            // gradients array
            float[,] gradients = new float[source.Width, source.Height];
            float maxGradient = float.NegativeInfinity;

            // do the job
            byte *src = (byte *)blurredImage.ImageData.ToPointer( );

            // allign pointer
            src += srcStride * startY + startX;

            // STEP 2 - calculate magnitude and edge orientation
            int p = 0;

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, src++, p++)
                {
                    gx = src[-srcStride + 1] + src[srcStride + 1]
                         - src[-srcStride - 1] - src[srcStride - 1]
                         + 2 * (src[1] - src[-1]);

                    gy = src[-srcStride - 1] + src[-srcStride + 1]
                         - src[srcStride - 1] - src[srcStride + 1]
                         + 2 * (src[-srcStride] - src[srcStride]);

                    // get gradient value
                    gradients[x, y] = (float)Math.Sqrt(gx * gx + gy * gy);
                    if (gradients[x, y] > maxGradient)
                    {
                        maxGradient = gradients[x, y];
                    }

                    // --- get orientation
                    if (gx == 0)
                    {
                        // can not divide by zero
                        orientation = (gy == 0) ? 0 : 90;
                    }
                    else
                    {
                        double div = (double)gy / gx;

                        // handle angles of the 2nd and 4th quads
                        if (div < 0)
                        {
                            orientation = 180 - System.Math.Atan(-div) * toAngle;
                        }
                        // handle angles of the 1st and 3rd quads
                        else
                        {
                            orientation = System.Math.Atan(div) * toAngle;
                        }

                        // get closest angle from 0, 45, 90, 135 set
                        if (orientation < 22.5)
                        {
                            orientation = 0;
                        }
                        else if (orientation < 67.5)
                        {
                            orientation = 45;
                        }
                        else if (orientation < 112.5)
                        {
                            orientation = 90;
                        }
                        else if (orientation < 157.5)
                        {
                            orientation = 135;
                        }
                        else
                        {
                            orientation = 0;
                        }
                    }

                    // save orientation
                    orients[p] = (byte)orientation;
                }
                src += srcOffset;
            }

            // STEP 3 - suppres non maximums
            byte *dst = (byte *)destination.ImageData.ToPointer( );

            // allign pointer
            dst += dstStride * startY + startX;

            p = 0;

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, dst++, p++)
                {
                    // get two adjacent pixels
                    switch (orients[p])
                    {
                    case 0:
                        leftPixel  = gradients[x - 1, y];
                        rightPixel = gradients[x + 1, y];
                        break;

                    case 45:
                        leftPixel  = gradients[x - 1, y + 1];
                        rightPixel = gradients[x + 1, y - 1];
                        break;

                    case 90:
                        leftPixel  = gradients[x, y + 1];
                        rightPixel = gradients[x, y - 1];
                        break;

                    case 135:
                        leftPixel  = gradients[x + 1, y + 1];
                        rightPixel = gradients[x - 1, y - 1];
                        break;
                    }
                    // compare current pixels value with adjacent pixels
                    if ((gradients[x, y] < leftPixel) || (gradients[x, y] < rightPixel))
                    {
                        *dst = 0;
                    }
                    else
                    {
                        *dst = (byte)(gradients[x, y] / maxGradient * 255);
                    }
                }
                dst += dstOffset;
            }

            // STEP 4 - hysteresis
            dst = (byte *)destination.ImageData.ToPointer( );
            // allign pointer
            dst += dstStride * startY + startX;

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, dst++)
                {
                    if (*dst < highThreshold)
                    {
                        if (*dst < lowThreshold)
                        {
                            // non edge
                            *dst = 0;
                        }
                        else
                        {
                            // check 8 neighboring pixels
                            if ((dst[-1] < highThreshold) &&
                                (dst[1] < highThreshold) &&
                                (dst[-dstStride - 1] < highThreshold) &&
                                (dst[-dstStride] < highThreshold) &&
                                (dst[-dstStride + 1] < highThreshold) &&
                                (dst[dstStride - 1] < highThreshold) &&
                                (dst[dstStride] < highThreshold) &&
                                (dst[dstStride + 1] < highThreshold))
                            {
                                *dst = 0;
                            }
                        }
                    }
                }
                dst += dstOffset;
            }

            // STEP 5 - draw black rectangle to remove those pixels, which were not processed
            // (this needs to be done for those cases, when filter is applied "in place" -
            //  source image is modified instead of creating new copy)
            Drawing.Rectangle(destination, rect, Color.Black);

            // release blurred image
            blurredImage.Dispose( );
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
        {
            int kernelHalf = kernelSize / 2;

            InitFilter( );

            if ( ( rect.Width <= kernelSize ) || ( rect.Height <= kernelSize ) )
            {
                ProcessWithEdgeChecks( source, destination, rect );
            }
            else
            {
                Rectangle safeArea = rect;
                safeArea.Inflate( -kernelHalf, -kernelHalf );

                if ( ( Environment.ProcessorCount > 1 ) && ( enableParallelProcessing ) )
                {
                    ProcessWithoutChecksParallel( source, destination, safeArea );
                }
                else
                {
                    ProcessWithoutChecks( source, destination, safeArea );
                }

                // top
                ProcessWithEdgeChecks( source, destination,
                    new Rectangle( rect.Left, rect.Top, rect.Width, kernelHalf ) );
                // bottom
                ProcessWithEdgeChecks( source, destination,
                    new Rectangle( rect.Left, rect.Bottom - kernelHalf, rect.Width, kernelHalf ) );
                // left
                ProcessWithEdgeChecks( source, destination,
                    new Rectangle( rect.Left, rect.Top + kernelHalf, kernelHalf, rect.Height - kernelHalf * 2 ) );
                // right
                ProcessWithEdgeChecks( source, destination,
                    new Rectangle( rect.Right - kernelHalf, rect.Top + kernelHalf, kernelHalf, rect.Height - kernelHalf  * 2 ) );
            }
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get source and destination images size
            var srcWidth  = sourceData.Width;
            var srcHeight = sourceData.Height;
            var dstWidth  = destinationData.Width;
            var dstHeight = destinationData.Height;

            var pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
            var srcStride = sourceData.Stride;
            var dstStride = destinationData.Stride;

            // find equations of four quadrilateral's edges ( f(x) = k*x + b )
            double kTop, bTop;
            double kBottom, bBottom;
            double kLeft, bLeft;
            double kRight, bRight;

            // top edge
            if (this.sourceQuadrilateral[1].X == this.sourceQuadrilateral[0].X)
            {
                kTop = 0;
                bTop = this.sourceQuadrilateral[1].X;
            }
            else
            {
                kTop = (double)(this.sourceQuadrilateral[1].Y - this.sourceQuadrilateral[0].Y) /
                       (this.sourceQuadrilateral[1].X - this.sourceQuadrilateral[0].X);
                bTop = (double)this.sourceQuadrilateral[0].Y - kTop * this.sourceQuadrilateral[0].X;
            }

            // bottom edge
            if (this.sourceQuadrilateral[2].X == this.sourceQuadrilateral[3].X)
            {
                kBottom = 0;
                bBottom = this.sourceQuadrilateral[2].X;
            }
            else
            {
                kBottom = (double)(this.sourceQuadrilateral[2].Y - this.sourceQuadrilateral[3].Y) /
                          (this.sourceQuadrilateral[2].X - this.sourceQuadrilateral[3].X);
                bBottom = (double)this.sourceQuadrilateral[3].Y - kBottom * this.sourceQuadrilateral[3].X;
            }

            // left edge
            if (this.sourceQuadrilateral[3].X == this.sourceQuadrilateral[0].X)
            {
                kLeft = 0;
                bLeft = this.sourceQuadrilateral[3].X;
            }
            else
            {
                kLeft = (double)(this.sourceQuadrilateral[3].Y - this.sourceQuadrilateral[0].Y) /
                        (this.sourceQuadrilateral[3].X - this.sourceQuadrilateral[0].X);
                bLeft = (double)this.sourceQuadrilateral[0].Y - kLeft * this.sourceQuadrilateral[0].X;
            }

            // right edge
            if (this.sourceQuadrilateral[2].X == this.sourceQuadrilateral[1].X)
            {
                kRight = 0;
                bRight = this.sourceQuadrilateral[2].X;
            }
            else
            {
                kRight = (double)(this.sourceQuadrilateral[2].Y - this.sourceQuadrilateral[1].Y) /
                         (this.sourceQuadrilateral[2].X - this.sourceQuadrilateral[1].X);
                bRight = (double)this.sourceQuadrilateral[1].Y - kRight * this.sourceQuadrilateral[1].X;
            }

            // some precalculated values
            var leftFactor  = (double)(this.sourceQuadrilateral[3].Y - this.sourceQuadrilateral[0].Y) / dstHeight;
            var rightFactor = (double)(this.sourceQuadrilateral[2].Y - this.sourceQuadrilateral[1].Y) / dstHeight;

            var srcY0 = this.sourceQuadrilateral[0].Y;
            var srcY1 = this.sourceQuadrilateral[1].Y;

            // do the job
            var baseSrc = (byte *)sourceData.ImageData.ToPointer( );
            var baseDst = (byte *)destinationData.ImageData.ToPointer( );

            // source width and height decreased by 1
            var ymax = srcHeight - 1;
            var xmax = srcWidth - 1;

            // coordinates of source points
            double dx1, dy1, dx2, dy2;
            int    sx1, sy1, sx2, sy2;

            // temporary pointers
            byte *p1, p2, p3, p4, p;

            // for each line
            for (var y = 0; y < dstHeight; y++)
            {
                var dst = baseDst + dstStride * y;

                // find corresponding Y on the left edge of the quadrilateral
                var yHorizLeft = leftFactor * y + srcY0;
                // find corresponding X on the left edge of the quadrilateral
                var xHorizLeft = (kLeft == 0) ? bLeft : (yHorizLeft - bLeft) / kLeft;

                // find corresponding Y on the right edge of the quadrilateral
                var yHorizRight = rightFactor * y + srcY1;
                // find corresponding X on the left edge of the quadrilateral
                var xHorizRight = (kRight == 0) ? bRight : (yHorizRight - bRight) / kRight;

                // find equation of the line joining points on the left and right edges
                double kHoriz, bHoriz;

                if (xHorizLeft == xHorizRight)
                {
                    kHoriz = 0;
                    bHoriz = xHorizRight;
                }
                else
                {
                    kHoriz = (yHorizRight - yHorizLeft) / (xHorizRight - xHorizLeft);
                    bHoriz = yHorizLeft - kHoriz * xHorizLeft;
                }

                var horizFactor = (xHorizRight - xHorizLeft) / dstWidth;

                if (!this.useInterpolation)
                {
                    for (var x = 0; x < dstWidth; x++)
                    {
                        var xs = horizFactor * x + xHorizLeft;
                        var ys = kHoriz * xs + bHoriz;

                        if ((xs >= 0) && (ys >= 0) && (xs < srcWidth) && (ys < srcHeight))
                        {
                            // get pointer to the pixel in the source image
                            p = baseSrc + ((int)ys * srcStride + (int)xs * pixelSize);
                            // copy pixel's values
                            for (var i = 0; i < pixelSize; i++, dst++, p++)
                            {
                                *dst = *p;
                            }
                        }
                        else
                        {
                            dst += pixelSize;
                        }
                    }
                }
                else
                {
                    for (var x = 0; x < dstWidth; x++)
                    {
                        var xs = horizFactor * x + xHorizLeft;
                        var ys = kHoriz * xs + bHoriz;

                        if ((xs >= 0) && (ys >= 0) && (xs < srcWidth) && (ys < srcHeight))
                        {
                            sx1 = (int)xs;
                            sx2 = (sx1 == xmax) ? sx1 : sx1 + 1;
                            dx1 = xs - sx1;
                            dx2 = 1.0 - dx1;

                            sy1 = (int)ys;
                            sy2 = (sy1 == ymax) ? sy1 : sy1 + 1;
                            dy1 = ys - sy1;
                            dy2 = 1.0 - dy1;

                            // get four points
                            p1  = p2 = baseSrc + sy1 * srcStride;
                            p1 += sx1 * pixelSize;
                            p2 += sx2 * pixelSize;

                            p3  = p4 = baseSrc + sy2 * srcStride;
                            p3 += sx1 * pixelSize;
                            p4 += sx2 * pixelSize;

                            // interpolate using 4 points
                            for (var i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++)
                            {
                                *dst = (byte)(
                                    dy2 * (dx2 * (*p1) + dx1 * (*p2)) +
                                    dy1 * (dx2 * (*p3) + dx1 * (*p4)));
                            }
                        }
                        else
                        {
                            dst += pixelSize;
                        }
                    }
                }
            }
        }
        // Perform image processing with checking pixels' coordinates to make sure those are in bounds
        private unsafe void ProcessWithEdgeChecks( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
        {
            int width  = source.Width;
            int height = source.Height;

            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = rect.Right;
            int stopY  = rect.Bottom;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize( source.PixelFormat ) / 8;
            int kernelHalf = kernelSize / 2;
            int bytesInKernelRow = kernelSize * pixelSize;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;

            int srcOffset = srcStride - rect.Width * pixelSize;
            int dstOffset = dstStride - rect.Width * pixelSize;

            // offset of the first kernel's pixel
            int srcKernelFistPixelOffset = kernelHalf * ( srcStride + pixelSize );
            // offset to move to the next kernel's pixel after processing one kernel's row
            int srcKernelOffset = srcStride - bytesInKernelRow;

            int rx, ry;
            int tx, ty;

            byte* src = (byte*) source.ImageData.ToPointer( );
            byte* dst = (byte*) destination.ImageData.ToPointer( );

            // allign pointers to the first pixel to process
            src += startY * srcStride + startX * pixelSize;
            dst += startY * dstStride + startX * pixelSize;

            if ( pixelSize > 1 )
            {
                // color images
                byte srcR, srcG, srcB;
                byte srcR0, srcG0, srcB0;
                byte* srcPixel;

                double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB;

                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefR = 0;
                        sCoefG = 0;
                        sCoefB = 0;
                        sMembR = 0;
                        sMembG = 0;
                        sMembB = 0;

                        srcR0 = src[RGB.R];
                        srcG0 = src[RGB.G];
                        srcB0 = src[RGB.B];

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;
                            ry = ty - kernelHalf;

                            if ( ( ry + y >= height ) || ( ry + y < 0 ) ) // bounds check
                            {
                                srcPixel -= srcStride;
                                continue;
                            }

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;
                                rx = tx - kernelHalf;

                                if ( ( rx + x >= width ) || ( rx + x < 0 ) ) // bounds check
                                {
                                    srcPixel -= pixelSize;
                                    continue;
                                }

                                srcR = srcPixel[RGB.R];
                                srcG = srcPixel[RGB.G];
                                srcB = srcPixel[RGB.B];

                                coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0];
                                coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0];
                                coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0];

                                sCoefR += coefR;
                                sCoefG += coefG;
                                sCoefB += coefB;

                                sMembR += coefR * srcR;
                                sMembG += coefG * srcG;
                                sMembB += coefB * srcB;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        dst[RGB.R] = (byte) ( sMembR / sCoefR );
                        dst[RGB.G] = (byte) ( sMembG / sCoefG );
                        dst[RGB.B] = (byte) ( sMembB / sCoefB );
                    }

                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                // 8bpp grayscale images
                byte srcC;
                byte srcC0;
                byte* srcPixel;
                double sCoefC, sMembC, coefC;

                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, src++, dst++ )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefC = 0;
                        sMembC = 0;

                        srcC0 = *src;

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;
                            ry = (int) ( ty - kernelHalf );

                            if ( ( ry + y >= height ) || ( ry + y < 0 ) ) // bounds check
                            {
                                srcPixel -= srcStride;
                                continue;
                            }

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;
                                rx = (int) ( tx - kernelHalf );

                                if ( ( rx + x >= source.Width ) || ( rx + x < 0 ) ) // bounds check
                                {
                                    srcPixel -= pixelSize;
                                    continue;
                                }

                                srcC = *( srcPixel );
                                coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0];

                                sCoefC += coefC;
                                sMembC += coefC * srcC;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        *dst = (byte) ( sMembC / sCoefC );
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
        }
Example #46
0
        /// <summary>
        /// Process new video frame.
        /// </summary>
        ///
        /// <param name="videoFrame">Video frame to process (detect motion in).</param>
        ///
        /// <remarks><para>Processes new frame from video source and detects motion in it.</para>
        ///
        /// <para>Check <see cref="MotionLevel"/> property to get information about amount of motion
        /// (changes) in the processed frame.</para>
        /// </remarks>
        ///
        public void ProcessFrame(UnmanagedImage videoFrame)
        {
            lock ( sync )
            {
                // check background frame
                if (backgroundFrame == null)
                {
                    lastTimeMeasurment = DateTime.Now;

                    // save image dimension
                    width  = videoFrame.Width;
                    height = videoFrame.Height;

                    // alocate memory for previous and current frames
                    backgroundFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
                    motionFrame     = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);

                    frameSize = motionFrame.Stride * height;

                    // temporary buffer
                    if (suppressNoise)
                    {
                        tempFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
                    }

                    // convert source frame to grayscale
                    Accord.Vision.Tools.ConvertToGrayscale(videoFrame, backgroundFrame);

                    return;
                }

                // check image dimension
                if ((videoFrame.Width != width) || (videoFrame.Height != height))
                {
                    return;
                }

                // convert current image to grayscale
                Accord.Vision.Tools.ConvertToGrayscale(videoFrame, motionFrame);

                unsafe
                {
                    // pointers to background and current frames
                    byte *backFrame;
                    byte *currFrame;
                    int   diff;

                    // update background frame
                    if (millisecondsPerBackgroundUpdate == 0)
                    {
                        // update background frame using frame counter as a base
                        if (++framesCounter == framesPerBackgroundUpdate)
                        {
                            framesCounter = 0;

                            backFrame = (byte *)backgroundFrame.ImageData.ToPointer( );
                            currFrame = (byte *)motionFrame.ImageData.ToPointer( );

                            for (int i = 0; i < frameSize; i++, backFrame++, currFrame++)
                            {
                                diff = *currFrame - *backFrame;
                                if (diff > 0)
                                {
                                    (*backFrame)++;
                                }
                                else if (diff < 0)
                                {
                                    (*backFrame)--;
                                }
                            }
                        }
                    }
                    else
                    {
                        // update background frame using timer as a base

                        // get current time and calculate difference
                        DateTime currentTime = DateTime.Now;
                        TimeSpan timeDff     = currentTime - lastTimeMeasurment;
                        // save current time as the last measurment
                        lastTimeMeasurment = currentTime;

                        int millisonds = (int)timeDff.TotalMilliseconds + millisecondsLeftUnprocessed;

                        // save remainder so it could be taken into account in the future
                        millisecondsLeftUnprocessed = millisonds % millisecondsPerBackgroundUpdate;
                        // get amount for background update
                        int updateAmount = (int)(millisonds / millisecondsPerBackgroundUpdate);

                        backFrame = (byte *)backgroundFrame.ImageData.ToPointer( );
                        currFrame = (byte *)motionFrame.ImageData.ToPointer( );

                        for (int i = 0; i < frameSize; i++, backFrame++, currFrame++)
                        {
                            diff = *currFrame - *backFrame;
                            if (diff > 0)
                            {
                                (*backFrame) += (byte)((diff < updateAmount) ? diff :  updateAmount);
                            }
                            else if (diff < 0)
                            {
                                (*backFrame) += (byte)((-diff < updateAmount) ? diff : -updateAmount);
                            }
                        }
                    }

                    backFrame = (byte *)backgroundFrame.ImageData.ToPointer( );
                    currFrame = (byte *)motionFrame.ImageData.ToPointer( );

                    // 1 - get difference between frames
                    // 2 - threshold the difference
                    for (int i = 0; i < frameSize; i++, backFrame++, currFrame++)
                    {
                        // difference
                        diff = (int)*currFrame - (int)*backFrame;
                        // treshold
                        *currFrame = ((diff >= differenceThreshold) || (diff <= differenceThresholdNeg)) ? (byte)255 : (byte)0;
                    }

                    if (suppressNoise)
                    {
                        // suppress noise and calculate motion amount
                        Accord.SystemTools.CopyUnmanagedMemory(tempFrame.ImageData, motionFrame.ImageData, frameSize);
                        erosionFilter.Apply(tempFrame, motionFrame);

                        if (keepObjectEdges)
                        {
                            Accord.SystemTools.CopyUnmanagedMemory(tempFrame.ImageData, motionFrame.ImageData, frameSize);
                            dilatationFilter.Apply(tempFrame, motionFrame);
                        }
                    }

                    // calculate amount of motion pixels
                    pixelsChanged = 0;
                    byte *motion = (byte *)motionFrame.ImageData.ToPointer( );

                    for (int i = 0; i < frameSize; i++, motion++)
                    {
                        pixelsChanged += (*motion & 1);
                    }
                }
            }
        }
Example #47
0
    /// <summary>
    /// Process the filter on the specified image.
    /// </summary>
    /// 
    /// <param name="sourceData">Source image data.</param>
    /// <param name="destinationData">Destination image data.</param>
    /// 
    protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
    {
      // get width and height
      int width = sourceData.Width;
      int height = sourceData.Height;
      PixelFormat srcPixelFormat = sourceData.PixelFormat;

      if (
          (srcPixelFormat == PixelFormat.Format24bppRgb) ||
          (srcPixelFormat == PixelFormat.Format32bppRgb) ||
          (srcPixelFormat == PixelFormat.Format32bppArgb))
      {
        int pixelSize = (srcPixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
        int srcOffset = sourceData.Stride - width * pixelSize;
        int dstOffset = destinationData.Stride - width;

        // do the job
        byte* src = (byte*)sourceData.ImageData.ToPointer();
        byte* dst = (byte*)destinationData.ImageData.ToPointer();

        // for each line
        for (int y = 0; y < height; y++)
        {
          // for each pixel
          for (int x = 0; x < width; x++, src += pixelSize, dst++)
          {
            *dst = (byte)(RedCoefficient * src[RGB.R] + GreenCoefficient * src[RGB.G] + BlueCoefficient * src[RGB.B]);
          }
          src += srcOffset;
          dst += dstOffset;
        }
      }
      else
      {
        int pixelSize = (srcPixelFormat == PixelFormat.Format48bppRgb) ? 3 : 4;
        byte* srcBase = (byte*)sourceData.ImageData.ToPointer();
        byte* dstBase = (byte*)destinationData.ImageData.ToPointer();
        int srcStride = sourceData.Stride;
        int dstStride = destinationData.Stride;

        // for each line
        for (int y = 0; y < height; y++)
        {
          ushort* src = (ushort*)(srcBase + y * srcStride);
          ushort* dst = (ushort*)(dstBase + y * dstStride);

          // for each pixel
          for (int x = 0; x < width; x++, src += pixelSize, dst++)
          {
            *dst = (ushort)(RedCoefficient * src[RGB.R] + GreenCoefficient * src[RGB.G] + BlueCoefficient * src[RGB.B]);
          }
        }
      }
    }
Example #48
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage source, UnmanagedImage destination, Rectangle rect)
        {
            int pixelSize = Image.GetPixelFormatSize(source.PixelFormat) / 8;

            // processing start and stop X,Y positions
            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = startX + rect.Width;
            int stopY  = startY + rect.Height;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;
            int srcOffset = srcStride - rect.Width * pixelSize;
            int dstOffset = dstStride - rect.Width * pixelSize;

            // loop and array indexes
            int i, j, t;
            // processing square's radius
            int radius = size >> 1;
            // number of elements
            int c;

            // array to hold pixel values (R, G, B)
            byte[] r = new byte[size * size];
            byte[] g = new byte[size * size];
            byte[] b = new byte[size * size];

            byte *src = (byte *)source.ImageData.ToPointer( );
            byte *dst = (byte *)destination.ImageData.ToPointer( );
            byte *p;

            // allign pointers to the first pixel to process
            src += (startY * srcStride + startX * pixelSize);
            dst += (startY * dstStride + startX * pixelSize);

            // do the processing job
            if (destination.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                // grayscale image

                // for each line
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, src++, dst++)
                    {
                        c = 0;

                        // for each kernel row
                        for (i = -radius; i <= radius; i++)
                        {
                            t = y + i;

                            // skip row
                            if (t < startY)
                            {
                                continue;
                            }
                            // break
                            if (t >= stopY)
                            {
                                break;
                            }

                            // for each kernel column
                            for (j = -radius; j <= radius; j++)
                            {
                                t = x + j;

                                // skip column
                                if (t < startX)
                                {
                                    continue;
                                }

                                if (t < stopX)
                                {
                                    g[c++] = src[i * srcStride + j];
                                }
                            }
                        }
                        // sort elements
                        Array.Sort(g, 0, c);
                        // get the median
                        *dst = g[c >> 1];
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                // RGB image

                // for each line
                for (int y = startY; y < stopY; y++)
                {
                    // for each pixel
                    for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize)
                    {
                        c = 0;

                        // for each kernel row
                        for (i = -radius; i <= radius; i++)
                        {
                            t = y + i;

                            // skip row
                            if (t < startY)
                            {
                                continue;
                            }
                            // break
                            if (t >= stopY)
                            {
                                break;
                            }

                            // for each kernel column
                            for (j = -radius; j <= radius; j++)
                            {
                                t = x + j;

                                // skip column
                                if (t < startX)
                                {
                                    continue;
                                }

                                if (t < stopX)
                                {
                                    p = &src[i * srcStride + j * pixelSize];

                                    r[c] = p[RGB.R];
                                    g[c] = p[RGB.G];
                                    b[c] = p[RGB.B];
                                    c++;
                                }
                            }
                        }

                        // sort elements
                        Array.Sort(r, 0, c);
                        Array.Sort(g, 0, c);
                        Array.Sort(b, 0, c);
                        // get the median
                        t          = c >> 1;
                        dst[RGB.R] = r[t];
                        dst[RGB.G] = g[t];
                        dst[RGB.B] = b[t];
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
        }
        private unsafe void ApplyBGGR( UnmanagedImage sourceData, UnmanagedImage destinationData )
        {
            int width  = sourceData.Width;
            int height = sourceData.Height;

            int widthM1  = width - 1;
            int heightM1 = height - 1;

            int srcStride = sourceData.Stride;
            int dstStride = destinationData.Stride;

            int srcStrideP1  = srcStride + 1;
            int srcStrideM1  = srcStride - 1;
            int srcMStride   = -srcStride;
            int srcMStrideP1 = srcMStride + 1;
            int srcMStrideM1 = srcMStride - 1;

            int srcOffset = srcStride - width;
            int dstOffset = dstStride - width * 3;

            // do the job
            byte * src = (byte*) sourceData.ImageData.ToPointer( );
            byte * dst = (byte*) destinationData.ImageData.ToPointer( );

            // --- process the first line

            // . . .
            // . B G 
            // . G R
            dst[RGB.R] = src[srcStrideP1];
            dst[RGB.G] = (byte) ( ( src[1] + src[srcStride] ) >> 1 );
            dst[RGB.B] = *src;

            src++;
            dst += 3;

            for ( int x = 1; x < widthM1; x += 2 )
            {
                // . . .
                // B G B 
                // G R G
                dst[RGB.R] = src[srcStride];
                dst[RGB.G] = (byte) ( ( *src + src[srcStrideM1] + src[srcStrideP1] ) / 3 );
                dst[RGB.B] = (byte) ( ( src[-1] + src[1] ) >> 1 );

                src++;
                dst += 3;

                // . . .
                // G B G
                // R G R
                dst[RGB.R] = (byte) ( ( src[srcStrideM1] + src[srcStrideP1] ) >> 1 );
                dst[RGB.G] = (byte) ( ( src[-1] + src[srcStride] + src[1] ) / 3 );
                dst[RGB.B] = *src;

                src++;
                dst += 3;
            }

            // . . .
            // B G . 
            // G R . 
            dst[RGB.R] = src[srcStride];
            dst[RGB.G] = (byte) ( ( *src + src[srcStrideM1] ) >> 1 );
            dst[RGB.B] = src[-1];


            // allign to the next line
            src += srcOffset + 1;
            dst += dstOffset + 3;

            // --- process all lines except the first one and the last one
            for ( int y = 1; y < heightM1; y += 2 )
            {
                // . B G 
                // . G R
                // . B G
                dst[RGB.R] = src[1];
                dst[RGB.G] = (byte) ( ( src[srcMStrideP1] + src[srcStrideP1] + *src ) / 3 );
                dst[RGB.B] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );

                dst += dstStride;
                src += srcStride;

                // ( y+1 pixel )
                // . G R
                // . B G
                // . G R
                dst[RGB.R] = (byte) ( ( src[srcMStrideP1] + src[srcStrideP1] ) >> 1 );
                dst[RGB.G] = (byte) ( ( src[1] + src[srcMStride] + src[srcStride] ) / 3 );
                dst[RGB.B] = *src;

                dst -= dstStride;
                src -= srcStride;

                src++;
                dst += 3;

                for ( int x = 1; x < widthM1; x += 2 )
                {
                    // B G B
                    // G R G
                    // B G B
                    dst[RGB.R] = *src;
                    dst[RGB.G] = (byte) ( ( src[srcMStride] + src[srcStride] + src[-1] + src[1] ) >> 2 );
                    dst[RGB.B] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] ) >> 2 );

                    // ( y+1 pixel )
                    // G R G
                    // B G B
                    // G R G
                    dst += dstStride;
                    src += srcStride;

                    dst[RGB.R] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );
                    dst[RGB.G] = (byte) ( ( *src + src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] ) / 5 );
                    dst[RGB.B] = (byte) ( ( src[-1] + src[1] ) >> 1 );

                    // ( y+1 x+1 pixel )
                    // R G R
                    // G B G
                    // R G R
                    dst += 3;
                    src++;

                    dst[RGB.R] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] ) >> 2 );
                    dst[RGB.G] = (byte) ( ( src[srcMStride] + src[srcStride] + src[-1] + src[1] ) >> 2 );
                    dst[RGB.B] = *src;

                    // ( x+1 pixel )
                    // G B G
                    // R G R
                    // G B G
                    dst -= dstStride;
                    src -= srcStride;

                    dst[RGB.R] = (byte) ( ( src[-1] + src[1] ) >> 1 );
                    dst[RGB.G] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] + src[srcStrideM1] + src[srcStrideP1] + *src ) / 5 );
                    dst[RGB.B] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );

                    dst += 3;
                    src++;
                }

                // B G .
                // G R .
                // B G .
                dst[RGB.R] = *src;
                dst[RGB.G] = (byte) ( ( src[srcMStride] + src[srcStride] + src[-1] ) / 3 );
                dst[RGB.B] = (byte) ( ( src[srcMStrideM1] + src[srcStrideM1] ) >> 1 );
                src += srcStride;
                dst += dstStride;

                // ( y+1 pixel )
                // G R .
                // B G .
                // G R .
                dst[RGB.R] = (byte) ( ( src[srcMStride] + src[srcStride] ) >> 1 );
                dst[RGB.G] = (byte) ( ( src[srcMStrideM1] + src[srcStrideM1] + *src ) / 3 );
                dst[RGB.B] = src[-1];

                // align to the next line
                src += srcOffset + 1;
                dst += dstOffset + 3;
            }

            // --- process the first line

            // . B G 
            // . G R 
            // . . .
            dst[RGB.R] = src[1];
            dst[RGB.G] = (byte) ( ( src[srcMStrideP1] + *src ) >> 1 );
            dst[RGB.B] = src[srcMStride];

            src++;
            dst += 3;

            for ( int x = 1; x < widthM1; x += 2 )
            {
                // B G B 
                // G R G 
                // . . .
                dst[RGB.R] = *src;
                dst[RGB.G] = (byte) ( ( src[-1] + src[1] + src[srcMStride] ) / 3 );
                dst[RGB.B] = (byte) ( ( src[srcMStrideM1] + src[srcMStrideP1] ) >> 1 );

                src++;
                dst += 3;

                // G B G
                // R G R 
                // . . .
                dst[RGB.R] = (byte) ( ( src[-1] + src[1] ) >> 1 );
                dst[RGB.G] = (byte) ( ( *src + src[srcMStrideM1] + src[srcMStrideP1] ) / 3 );
                dst[RGB.B] = src[srcMStride];

                src++;
                dst += 3;
            }

            // B G . 
            // G R . 
            // . . .
            dst[RGB.R] = *src;
            dst[RGB.G] = (byte) ( ( src[srcMStride] + src[-1] ) >> 1 );
            dst[RGB.B] = src[srcMStrideM1];
        }
Example #50
0
 protected abstract void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData);
 /// <summary>
 /// Apply filter to an image (not implemented).
 /// </summary>
 /// 
 /// <param name="sourceImage">Source image to be processed.</param>
 /// <param name="destinationImage">Destination image to store filter's result.</param>
 /// 
 /// <exception cref="NotImplementedException">The method is not implemented.</exception>
 /// 
 public void Apply( UnmanagedImage sourceImage, UnmanagedImage destinationImage )
 {
     throw new NotImplementedException( "The method is not implemented filter." );
 }
Example #52
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage source, UnmanagedImage destination)
        {
            int pixelSize = Image.GetPixelFormatSize(source.PixelFormat) / 8;

            // processing start and stop X,Y positions
            int width  = source.Width;
            int height = source.Height;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;
            int dstOffset = dstStride - width * pixelSize;

            // coordinates of source points
            double ox, oy, dx1, dy1, dx2, dy2;
            int    ox1, oy1, ox2, oy2;

            // width and height decreased by 1
            int ymax = height - 1;
            int xmax = width - 1;

            byte *src = (byte *)source.ImageData.ToPointer( );
            byte *dst = (byte *)destination.ImageData.ToPointer( );
            byte *p1, p2, p3, p4;

            double xFactor = 2 * Math.PI * xWavesCount / width;
            double yFactor = 2 * Math.PI * yWavesCount / height;

            // for each line
            for (int y = 0; y < height; y++)
            {
                double yPart = Math.Sin(yFactor * y) * yWavesAmplitude;

                // for each pixel
                for (int x = 0; x < width; x++)
                {
                    ox = x + yPart;
                    oy = y + Math.Cos(xFactor * x) * xWavesAmplitude;

                    // check if the source pixel is inside of image
                    if ((ox >= 0) && (oy >= 0) && (ox < width) && (oy < height))
                    {
                        // perform bilinear interpolation
                        oy1 = (int)oy;
                        oy2 = (oy1 == ymax) ? oy1 : oy1 + 1;
                        dy1 = oy - (double)oy1;
                        dy2 = 1.0 - dy1;

                        ox1 = (int)ox;
                        ox2 = (ox1 == xmax) ? ox1 : ox1 + 1;
                        dx1 = ox - (double)ox1;
                        dx2 = 1.0 - dx1;

                        p1 = src + oy1 * srcStride + ox1 * pixelSize;
                        p2 = src + oy1 * srcStride + ox2 * pixelSize;
                        p3 = src + oy2 * srcStride + ox1 * pixelSize;
                        p4 = src + oy2 * srcStride + ox2 * pixelSize;

                        for (int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++)
                        {
                            *dst = (byte)(
                                dy2 * (dx2 * (*p1) + dx1 * (*p2)) +
                                dy1 * (dx2 * (*p3) + dx1 * (*p4)));
                        }
                    }
                    else
                    {
                        for (int i = 0; i < pixelSize; i++, dst++)
                        {
                            *dst = 0;
                        }
                    }
                }
                dst += dstOffset;
            }
        }
Example #53
0
        /// <summary>
        /// Calculate binarization threshold for the given image.
        /// </summary>
        /// 
        /// <param name="image">Image to calculate binarization threshold for.</param>
        /// <param name="rect">Rectangle to calculate binarization threshold for.</param>
        /// 
        /// <returns>Returns binarization threshold.</returns>
        /// 
        /// <remarks><para>The method is used to calculate binarization threshold only. The threshold
        /// later may be applied to the image using <see cref="Threshold"/> image processing filter.</para></remarks>
        /// 
        /// <exception cref="UnsupportedImageFormatException">Source pixel format is not supported by the routine. It should be
        /// 8 bpp grayscale (indexed) image.</exception>
        /// 
        public int CalculateThreshold( UnmanagedImage image, Rectangle rect )
        {
            if ( image.PixelFormat != PixelFormat.Format8bppIndexed )
                throw new UnsupportedImageFormatException( "Source pixel format is not supported by the routine." );

            int calculatedThreshold = 0;

            // get start and stop X-Y coordinates
            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;
            int offset  = image.Stride - rect.Width;

            // histogram array
            int[] integerHistogram = new int[256];
            double[] histogram = new double[256];

            unsafe
            {
                // collect histogram first
                byte* ptr = (byte*) image.ImageData.ToPointer( );

                // allign pointer to the first pixel to process
                ptr += ( startY * image.Stride + startX );

                // for each line	
                for ( int y = startY; y < stopY; y++ )
                {
                    // for each pixel
                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        integerHistogram[*ptr]++;
                    }
                    ptr += offset;
                }

                // pixels count in the processing region
                int pixelCount = ( stopX - startX ) * ( stopY - startY );
                // mean value of the processing region
                double imageMean = 0;

                for ( int i = 0; i < 256; i++ )
                {
                    histogram[i] = (double) integerHistogram[i] / pixelCount;
                    imageMean += histogram[i] * i;
                }

                double max = double.MinValue;

                // initial class probabilities
                double class1Probability = 0;
                double class2Probability = 1;

                // initial class 1 mean value
                double class1MeanInit = 0;

                // check all thresholds
                for ( int t = 0; ( t < 256 ) && ( class2Probability > 0 ); t++ )
                {
                    // calculate class means for the given threshold
                    double class1Mean = class1MeanInit;
                    double class2Mean = ( imageMean - ( class1Mean * class1Probability ) ) / class2Probability;

                    // calculate between class variance
                    double betweenClassVariance = ( class1Probability ) * ( 1.0 - class1Probability ) * Math.Pow( class1Mean - class2Mean, 2 );

                    // check if we found new threshold candidate
                    if ( betweenClassVariance > max )
                    {
                        max = betweenClassVariance;
                        calculatedThreshold = t;
                    }

                    // update initial probabilities and mean value
                    class1MeanInit *= class1Probability;

                    class1Probability += histogram[t];
                    class2Probability -= histogram[t];

                    class1MeanInit += (double) t * (double) histogram[t];

                    if ( class1Probability != 0 )
                    {
                        class1MeanInit /= class1Probability;
                    }
                }
            }

            return calculatedThreshold;
        }
Example #54
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        ///
        /// <exception cref="InvalidImagePropertiesException">Texture size does not match image size.</exception>
        /// <exception cref="ApplicationException">Filters should not change image dimension.</exception>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            // get source image dimension
            var width  = sourceData.Width;
            var height = sourceData.Height;

            // if generator was specified, then generate a texture
            // otherwise use provided texture
            if (textureGenerator != null)
            {
                texture = textureGenerator.Generate(width, height);
            }
            else
            {
                // check existing texture
                if ((texture.GetLength(0) != height) || (texture.GetLength(1) != width))
                {
                    // sorry, but source image must have the same dimension as texture
                    throw new InvalidImagePropertiesException("Texture size does not match image size.");
                }
            }

            // apply first filter
            var filteredImage1 = filter1.Apply(sourceData);

            // check size of the result image
            if ((width != filteredImage1.Width) || (height != filteredImage1.Height))
            {
                filteredImage1.Dispose();
                throw new ApplicationException("Filters should not change image dimension.");
            }

            // convert 1st image to RGB if required
            if (filteredImage1.PixelFormat == PixelFormat.Format8bppIndexed)
            {
                var coloringFilter = new GrayscaleToRGB();
                var temp           = coloringFilter.Apply(filteredImage1);
                filteredImage1.Dispose();
                filteredImage1 = temp;
            }

            UnmanagedImage filteredImage2 = null;

            // apply second filter, if it was specified
            if (filter2 != null)
            {
                filteredImage2 = filter2.Apply(sourceData);
                // check size of the result image
                if ((width != filteredImage2.Width) || (height != filteredImage2.Height))
                {
                    filteredImage1.Dispose();
                    filteredImage2.Dispose();
                    // we are not handling such situations yet
                    throw new ApplicationException("Filters should not change image dimension.");
                }

                // convert 2nd image to RGB if required
                if (filteredImage2.PixelFormat == PixelFormat.Format8bppIndexed)
                {
                    var coloringFilter = new GrayscaleToRGB();
                    var temp           = coloringFilter.Apply(filteredImage2);
                    filteredImage2.Dispose();
                    filteredImage2 = temp;
                }
            }

            // use source image as a second image, if second filter is not set
            if (filteredImage2 == null)
            {
                filteredImage2 = sourceData;
            }

            // do the job
            unsafe
            {
                var dst  = (byte *)destinationData.ImageData.ToPointer();
                var src1 = (byte *)filteredImage1.ImageData.ToPointer();
                var src2 = (byte *)filteredImage2.ImageData.ToPointer();

                var dstOffset  = destinationData.Stride - 3 * width;
                var src1Offset = filteredImage1.Stride - 3 * width;
                var src2Offset = filteredImage2.Stride - 3 * width;

                if (preserveLevel != 0.0)
                {
                    // for each line
                    for (var y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (var x = 0; x < width; x++)
                        {
                            double t1 = texture[y, x];
                            var    t2 = 1 - t1;

                            for (var i = 0; i < 3; i++, src1++, src2++, dst++)
                            {
                                *dst = (byte)System.Math.Min(255.0f,
                                                             filterLevel * (t1 * (*src1) + t2 * (*src2)) +
                                                             preserveLevel * (*src2));
                            }
                        }
                        src1 += src1Offset;
                        src2 += src2Offset;
                        dst  += dstOffset;
                    }
                }
                else
                {
                    // for each line
                    for (var y = 0; y < height; y++)
                    {
                        // for each pixel
                        for (var x = 0; x < width; x++)
                        {
                            double t1 = texture[y, x];
                            var    t2 = 1 - t1;

                            for (var i = 0; i < 3; i++, src1++, src2++, dst++)
                            {
                                *dst = (byte)System.Math.Min(255.0f, t1 * *src1 + t2 * *src2);
                            }
                        }
                        src1 += src1Offset;
                        src2 += src2Offset;
                        dst  += dstOffset;
                    }
                }
            }

            // dispose temp images
            filteredImage1.Dispose();
            if (filteredImage2 != sourceData)
            {
                filteredImage2.Dispose();
            }
        }
        /// <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 startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;

            if ( image.PixelFormat == PixelFormat.Format8bppIndexed )
            {
                int offset = image.Stride - rect.Width;

                // do the job
                byte* ptr = (byte*) image.ImageData.ToPointer( );

                // allign pointer to the first pixel to process
                ptr += ( startY * image.Stride + startX );

                // for each line	
                for ( int y = startY; y < stopY; y++ )
                {
                    // for each pixel
                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        *ptr = (byte) ( ( *ptr >= threshold ) ? 255 : 0 );
                    }
                    ptr += offset;
                }
            }
            else
            {
                byte* basePtr = (byte*) image.ImageData.ToPointer( ) + startX * 2;
                int stride = image.Stride;

                // for each line	
                for ( int y = startY; y < stopY; y++ )
                {
                    ushort* ptr = (ushort*) ( basePtr + stride * y );

                    // for each pixel
                    for ( int x = startX; x < stopX; x++, ptr++ )
                    {
                        *ptr = (ushort) ( ( *ptr >= threshold ) ? 65535 : 0 );
                    }
                }
            }
        }
Example #56
0
        private unsafe void ProcessImage(UnmanagedImage image, Rectangle rect, byte *mask, int maskLineSize)
        {
            UnmanagedImage unmanagedImage = baseFilter.Apply(image);

            if (image.Width != unmanagedImage.Width || image.Height != unmanagedImage.Height)
            {
                throw new ArgumentException("Base filter must not change image size.");
            }
            int num     = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8;
            int top     = rect.Top;
            int num2    = top + rect.Height;
            int left    = rect.Left;
            int num3    = left + rect.Width;
            int stride  = image.Stride;
            int stride2 = unmanagedImage.Stride;
            int num4    = maskLineSize - rect.Width;

            mask += maskLineSize * top + left;
            if (num <= 4 && num != 2)
            {
                byte *ptr  = (byte *)image.ImageData.ToPointer() + (long)stride * (long)top + (long)num * (long)left;
                int   num5 = stride - rect.Width * num;
                byte *ptr2 = (byte *)unmanagedImage.ImageData.ToPointer() + (long)stride2 * (long)top + (long)num * (long)left;
                int   num6 = stride2 - rect.Width * num;
                switch (num)
                {
                case 2:
                    break;

                case 1:
                {
                    for (int j = top; j < num2; j++)
                    {
                        int num8 = left;
                        while (num8 < num3)
                        {
                            if (*mask != 0)
                            {
                                *ptr = *ptr2;
                            }
                            num8++;
                            ptr++;
                            ptr2++;
                            mask++;
                        }
                        ptr  += num5;
                        ptr2 += num6;
                        mask += num4;
                    }
                    break;
                }

                case 3:
                {
                    for (int k = top; k < num2; k++)
                    {
                        int num9 = left;
                        while (num9 < num3)
                        {
                            if (*mask != 0)
                            {
                                ptr[2] = ptr2[2];
                                ptr[1] = ptr2[1];
                                *ptr = *ptr2;
                            }
                            num9++;
                            ptr  += 3;
                            ptr2 += 3;
                            mask++;
                        }
                        ptr  += num5;
                        ptr2 += num6;
                        mask += num4;
                    }
                    break;
                }

                case 4:
                {
                    for (int i = top; i < num2; i++)
                    {
                        int num7 = left;
                        while (num7 < num3)
                        {
                            if (*mask != 0)
                            {
                                ptr[2] = ptr2[2];
                                ptr[1] = ptr2[1];
                                *ptr = *ptr2;
                                ptr[3] = ptr2[3];
                            }
                            num7++;
                            ptr  += 4;
                            ptr2 += 4;
                            mask++;
                        }
                        ptr  += num5;
                        ptr2 += num6;
                        mask += num4;
                    }
                    break;
                }
                }
                return;
            }
            byte *ptr3 = (byte *)image.ImageData.ToPointer() + (long)stride * (long)top + (long)num * (long)left;
            byte *ptr4 = (byte *)unmanagedImage.ImageData.ToPointer() + (long)stride2 * (long)top + (long)num * (long)left;

            switch (num)
            {
            case 2:
            {
                for (int m = top; m < num2; m++)
                {
                    ushort *ptr7  = (ushort *)ptr3;
                    ushort *ptr8  = (ushort *)ptr4;
                    int     num11 = left;
                    while (num11 < num3)
                    {
                        if (*mask != 0)
                        {
                            *ptr7 = *ptr8;
                        }
                        num11++;
                        ptr7++;
                        ptr8++;
                        mask++;
                    }
                    ptr3 += stride;
                    ptr4 += stride2;
                    mask += num4;
                }
                break;
            }

            case 6:
            {
                for (int n = top; n < num2; n++)
                {
                    ushort *ptr9  = (ushort *)ptr3;
                    ushort *ptr10 = (ushort *)ptr4;
                    int     num12 = left;
                    while (num12 < num3)
                    {
                        if (*mask != 0)
                        {
                            ptr9[2] = ptr10[2];
                            ptr9[1] = ptr10[1];
                            *ptr9 = *ptr10;
                        }
                        num12++;
                        ptr9  += 3;
                        ptr10 += 3;
                        mask++;
                    }
                    ptr3 += stride;
                    ptr4 += stride2;
                    mask += num4;
                }
                break;
            }

            case 8:
            {
                for (int l = top; l < num2; l++)
                {
                    ushort *ptr5  = (ushort *)ptr3;
                    ushort *ptr6  = (ushort *)ptr4;
                    int     num10 = left;
                    while (num10 < num3)
                    {
                        if (*mask != 0)
                        {
                            ptr5[2] = ptr6[2];
                            ptr5[1] = ptr6[1];
                            *ptr5 = *ptr6;
                            ptr5[3] = ptr6[3];
                        }
                        num10++;
                        ptr5 += 4;
                        ptr6 += 4;
                        mask++;
                    }
                    ptr3 += stride;
                    ptr4 += stride2;
                    mask += num4;
                }
                break;
            }
            }
        }
Example #57
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="sourceData">Source image data.</param>
        /// <param name="destinationData">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        /// 
        protected override unsafe void ProcessFilter( UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect )
        {
            PixelFormat pixelFormat = sourceData.PixelFormat;

            // processing start and stop X,Y positions
            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;

            // structuring element's radius
            int r = size >> 1;

            // flag to indicate if at least one pixel for the given structuring element was found
            bool foundSomething;

            if ( ( pixelFormat == PixelFormat.Format8bppIndexed ) || ( pixelFormat == PixelFormat.Format24bppRgb ) )
            {
                int pixelSize = ( pixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3;

                int dstStride = destinationData.Stride;
                int srcStride = sourceData.Stride;

                // base pointers
                byte* baseSrc = (byte*) sourceData.ImageData.ToPointer( );
                byte* baseDst = (byte*) destinationData.ImageData.ToPointer( );

                // allign pointers by X
                baseSrc += ( startX * pixelSize );
                baseDst += ( startX * pixelSize );

                if ( pixelFormat == PixelFormat.Format8bppIndexed )
                {
                    // grayscale image

                    // compute each line
                    for ( int y = startY; y < stopY; y++ )
                    {
                        byte* src = baseSrc + y * srcStride;
                        byte* dst = baseDst + y * dstStride;

                        byte min, v;

                        // loop and array indexes
                        int t, ir, jr, i, j;

                        // for each pixel
                        for ( int x = startX; x < stopX; x++, src++, dst++ )
                        {
                            min = 255;
                            foundSomething = false;

                            // for each structuring element's row
                            for ( i = 0; i < size; i++ )
                            {
                                ir = i - r;
                                t = y + ir;

                                // skip row
                                if ( t < startY )
                                    continue;
                                // break
                                if ( t >= stopY )
                                    break;

                                // for each structuring element's column
                                for ( j = 0; j < size; j++ )
                                {
                                    jr = j - r;
                                    t = x + jr;

                                    // skip column
                                    if ( t < startX )
                                        continue;
                                    if ( t < stopX )
                                    {
                                        if ( se[i, j] == 1 )
                                        {
                                            foundSomething = true;
                                            // get new MIN value
                                            v = src[ir * srcStride + jr];
                                            if ( v < min )
                                                min = v;
                                        }
                                    }
                                }
                            }
                            // result pixel
                            *dst = ( foundSomething ) ? min : *src;
                        }
                    }
                }
                else
                {
                    // 24 bpp color image

                    // compute each line
                    for ( int y = startY; y < stopY; y++ )
                    {
                        byte* src = baseSrc + y * srcStride;
                        byte* dst = baseDst + y * dstStride;

                        byte minR, minG, minB, v;
                        byte* p;

                        // loop and array indexes
                        int t, ir, jr, i, j;

                        // for each pixel
                        for ( int x = startX; x < stopX; x++, src += 3, dst += 3 )
                        {
                            minR = minG = minB = 255;
                            foundSomething = false;

                            // for each structuring element's row
                            for ( i = 0; i < size; i++ )
                            {
                                ir = i - r;
                                t = y + ir;

                                // skip row
                                if ( t < startY )
                                    continue;
                                // break
                                if ( t >= stopY )
                                    break;

                                // for each structuring element's column
                                for ( j = 0; j < size; j++ )
                                {
                                    jr = j - r;
                                    t = x + jr;

                                    // skip column
                                    if ( t < startX )
                                        continue;
                                    if ( t < stopX )
                                    {
                                        if ( se[i, j] == 1 )
                                        {
                                            foundSomething = true;
                                            // get new MIN values
                                            p = &src[ir * srcStride + jr * 3];

                                            // red
                                            v = p[RGB.R];
                                            if ( v < minR )
                                                minR = v;

                                            // green
                                            v = p[RGB.G];
                                            if ( v < minG )
                                                minG = v;

                                            // blue
                                            v = p[RGB.B];
                                            if ( v < minB )
                                                minB = v;
                                        }
                                    }
                                }
                            }
                            // result pixel
                            if ( foundSomething )
                            {
                                dst[RGB.R] = minR;
                                dst[RGB.G] = minG;
                                dst[RGB.B] = minB;
                            }
                            else
                            {
                                dst[RGB.R] = src[RGB.R];
                                dst[RGB.G] = src[RGB.G];
                                dst[RGB.B] = src[RGB.B];
                            }
                        }
                    }
                }
            }
            else
            {
                int pixelSize = ( pixelFormat == PixelFormat.Format16bppGrayScale ) ? 1 : 3;

                int dstStride = destinationData.Stride / 2;
                int srcStride = sourceData.Stride / 2;

                // base pointers
                ushort* baseSrc = (ushort*) sourceData.ImageData.ToPointer( );
                ushort* baseDst = (ushort*) destinationData.ImageData.ToPointer( );

                // allign pointers by X
                baseSrc += ( startX * pixelSize );
                baseDst += ( startX * pixelSize );

                if ( pixelFormat == PixelFormat.Format16bppGrayScale )
                {
                    // 16 bpp grayscale image

                    // compute each line
                    for ( int y = startY; y < stopY; y++ )
                    {
                        ushort* src = baseSrc + y * srcStride;
                        ushort* dst = baseDst + y * dstStride;

                        ushort min, v;

                        // loop and array indexes
                        int t, ir, jr, i, j;

                        // for each pixel
                        for ( int x = startX; x < stopX; x++, src++, dst++ )
                        {
                            min = 65535;
                            foundSomething = false;

                            // for each structuring element's row
                            for ( i = 0; i < size; i++ )
                            {
                                ir = i - r;
                                t = y + ir;

                                // skip row
                                if ( t < startY )
                                    continue;
                                // break
                                if ( t >= stopY )
                                    break;

                                // for each structuring element's column
                                for ( j = 0; j < size; j++ )
                                {
                                    jr = j - r;
                                    t = x + jr;

                                    // skip column
                                    if ( t < startX )
                                        continue;
                                    if ( t < stopX )
                                    {
                                        if ( se[i, j] == 1 )
                                        {
                                            foundSomething = true;
                                            // get new MIN value
                                            v = src[ir * srcStride + jr];
                                            if ( v < min )
                                                min = v;
                                        }
                                    }
                                }
                            }
                            // result pixel
                            *dst = ( foundSomething ) ? min : *src;

                        }
                    }
                }
                else
                {
                    // 48 bpp color image

                    // compute each line
                    for ( int y = startY; y < stopY; y++ )
                    {
                        ushort* src = baseSrc + y * srcStride;
                        ushort* dst = baseDst + y * dstStride;

                        ushort  minR, minG, minB, v;
                        ushort* p;

                        // loop and array indexes
                        int t, ir, jr, i, j;

                        // for each pixel
                        for ( int x = startX; x < stopX; x++, src += 3, dst += 3 )
                        {
                            minR = minG = minB = 65535;
                            foundSomething = false;

                            // for each structuring element's row
                            for ( i = 0; i < size; i++ )
                            {
                                ir = i - r;
                                t = y + ir;

                                // skip row
                                if ( t < startY )
                                    continue;
                                // break
                                if ( t >= stopY )
                                    break;

                                // for each structuring element's column
                                for ( j = 0; j < size; j++ )
                                {
                                    jr = j - r;
                                    t = x + jr;

                                    // skip column
                                    if ( t < startX )
                                        continue;
                                    if ( t < stopX )
                                    {
                                        if ( se[i, j] == 1 )
                                        {
                                            foundSomething = true;
                                            // get new MIN values
                                            p = &src[ir * srcStride + jr * 3];

                                            // red
                                            v = p[RGB.R];
                                            if ( v < minR )
                                                minR = v;

                                            // green
                                            v = p[RGB.G];
                                            if ( v < minG )
                                                minG = v;

                                            // blue
                                            v = p[RGB.B];
                                            if ( v < minB )
                                                minB = v;
                                        }
                                    }
                                }
                            }
                            // result pixel
                            if ( foundSomething )
                            {
                                dst[RGB.R] = minR;
                                dst[RGB.G] = minG;
                                dst[RGB.B] = minB;
                            }
                            else
                            {
                                dst[RGB.R] = src[RGB.R];
                                dst[RGB.G] = src[RGB.G];
                                dst[RGB.B] = src[RGB.B];
                            }
                        }
                    }
                }
            }
        }
Example #58
0
 public MaskedFilter(IFilter baseFiler, UnmanagedImage unmanagedMaskImage)
 {
     BaseFilter         = baseFiler;
     UnmanagedMaskImage = unmanagedMaskImage;
 }
Example #59
0
 /// <summary>
 /// Process the filter on the specified image.
 /// </summary>
 ///
 /// <param name="image">Source image data.</param>
 /// <param name="rect">Image rectangle for processing by the filter.</param>
 ///
 protected abstract unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect);
Example #60
0
 /// <summary>
 /// Apply filter to an image in unmanaged memory.
 /// </summary>
 ///
 /// <param name="sourceImage">Source image in unmanaged memory to apply filter to.</param>
 /// <param name="destinationImage">Destination image in unmanaged memory to put result into.</param>
 ///
 /// <remarks><para>The method keeps the source image unchanged and puts result of image processing
 /// into destination image.</para>
 ///
 /// <para><note>The destination image must have the same width and height as source image. Also
 /// destination image must have pixel format, which is expected by particular filter (see
 /// <see cref="FormatTranslations"/> property for information about pixel format conversions).</note></para>
 /// </remarks>
 ///
 /// <exception cref="UnsupportedImageFormatException">Unsupported pixel format of the source image.</exception>
 /// <exception cref="InvalidImagePropertiesException">Incorrect destination pixel format.</exception>
 /// <exception cref="InvalidImagePropertiesException">Destination image has wrong width and/or height.</exception>
 ///
 public void Apply(UnmanagedImage sourceImage, UnmanagedImage destinationImage)
 {
     dilation.Apply(sourceImage, destinationImage);
     errosion.ApplyInPlace(destinationImage);
 }