示例#1
0
        /// <summary>
        /// Flips an image along a specified axis
        /// </summary>
        /// <param name="imageA">First image</param>
        /// <param name="imageB">Second image</param>
        /// <returns>Difference image</returns>
        public static Shared <Image> AbsDiff(this Image imageA, Image imageB)
        {
            if (imageA.Width != imageB.Width || imageA.Height != imageB.Height || imageA.PixelFormat != imageB.PixelFormat)
            {
                throw new System.Exception("Images sizes/types don't match");
            }

            Shared <Image> dstImage = ImagePool.GetOrCreate(imageA.Width, imageA.Height, imageA.PixelFormat);

            unsafe
            {
                int   bytesPerPixel = PixelFormatHelper.GetBytesPerPixel(imageA.PixelFormat);
                byte *srcRowA       = (byte *)imageA.ImageData.ToPointer();
                byte *srcRowB       = (byte *)imageB.ImageData.ToPointer();
                byte *dstRow        = (byte *)dstImage.Resource.ImageData.ToPointer();
                for (int i = 0; i < imageA.Height; i++)
                {
                    byte *srcColA = srcRowA;
                    byte *srcColB = srcRowB;
                    byte *dstCol = dstRow;
                    int   delta0, delta1, delta2, delta3;
                    for (int j = 0; j < imageA.Width; j++)
                    {
                        switch (imageA.PixelFormat)
                        {
                        case PixelFormat.BGRA_32bpp:
                            delta0    = srcColA[0] - srcColB[0];
                            delta1    = srcColA[1] - srcColB[1];
                            delta2    = srcColA[2] - srcColB[2];
                            delta3    = srcColA[3] - srcColB[3];
                            dstCol[0] = (byte)((delta0 < 0) ? -delta0 : delta0);
                            dstCol[1] = (byte)((delta1 < 0) ? -delta1 : delta1);
                            dstCol[2] = (byte)((delta2 < 0) ? -delta2 : delta2);
                            dstCol[3] = (byte)((delta3 < 0) ? -delta3 : delta3);
                            break;

                        case PixelFormat.BGRX_32bpp:
                            delta0    = srcColA[0] - srcColB[0];
                            delta1    = srcColA[1] - srcColB[1];
                            delta2    = srcColA[2] - srcColB[2];
                            dstCol[0] = (byte)((delta0 < 0) ? -delta0 : delta0);
                            dstCol[1] = (byte)((delta1 < 0) ? -delta1 : delta1);
                            dstCol[2] = (byte)((delta2 < 0) ? -delta2 : delta2);
                            break;

                        case PixelFormat.BGR_24bpp:
                            delta0    = srcColA[0] - srcColB[0];
                            delta1    = srcColA[1] - srcColB[1];
                            delta2    = srcColA[2] - srcColB[2];
                            dstCol[0] = (byte)((delta0 < 0) ? -delta0 : delta0);
                            dstCol[1] = (byte)((delta1 < 0) ? -delta1 : delta1);
                            dstCol[2] = (byte)((delta2 < 0) ? -delta2 : delta2);
                            break;

                        case PixelFormat.Gray_16bpp:
                            delta0 = ((ushort *)srcColA)[0] - ((ushort *)srcColB)[0];
                            ((ushort *)dstCol)[0] = (ushort)((delta0 < 0) ? -delta0 : delta0);
                            break;

                        case PixelFormat.Gray_8bpp:
                            delta0    = srcColA[0] - srcColB[0];
                            dstCol[0] = (byte)((delta0 < 0) ? -delta0 : delta0);
                            break;

                        case PixelFormat.RGBA_64bpp:
                            delta0 = (ushort)(((ushort *)srcColA)[0] - ((ushort *)srcColB)[0]);
                            delta1 = (ushort)(((ushort *)srcColA)[1] - ((ushort *)srcColB)[1]);
                            delta2 = (ushort)(((ushort *)srcColA)[2] - ((ushort *)srcColB)[2]);
                            delta3 = (ushort)(((ushort *)srcColA)[3] - ((ushort *)srcColB)[3]);
                            ((ushort *)dstCol)[0] = (ushort)((delta0 < 0) ? -delta0 : delta0);
                            ((ushort *)dstCol)[1] = (ushort)((delta1 < 0) ? -delta1 : delta1);
                            ((ushort *)dstCol)[2] = (ushort)((delta2 < 0) ? -delta2 : delta2);
                            ((ushort *)dstCol)[3] = (ushort)((delta3 < 0) ? -delta3 : delta3);
                            break;

                        default:
                            throw new System.Exception("Unexpected image format");
                        }

                        srcColA += bytesPerPixel;
                        srcColB += bytesPerPixel;
                        dstCol  += bytesPerPixel;
                    }

                    srcRowA += imageA.Stride;
                    srcRowB += imageB.Stride;
                    dstRow  += dstImage.Resource.Stride;
                }
            }

            return(dstImage);
        }
示例#2
0
        /// <summary>
        /// Copies a source image into a destination image using the specified masking image.
        /// Only pixels in the source image whose corresponding mask image pixels are > 0
        /// are copied to the destination image. Only pixels from the srcRect are copied
        /// to the destination rect.
        /// </summary>
        /// <param name="srcImage">Source image</param>
        /// <param name="srcRect">Source rectangle to copy from</param>
        /// <param name="dstImage">Destination image</param>
        /// <param name="dstRect">Destination rectangle to copy to</param>
        /// <param name="maskImage">Masking image</param>
        public static void CopyTo(this Image srcImage, Rectangle srcRect, Image dstImage, Rectangle dstRect, Image maskImage)
        {
            if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height)
            {
                throw new System.Exception("Source and destination rectangles sizes must match");
            }

            if (maskImage != null)
            {
                if (srcImage.Width != maskImage.Width || srcImage.Height != maskImage.Height)
                {
                    throw new System.Exception("Mask image size must match source image size");
                }

                if (maskImage.PixelFormat != PixelFormat.Gray_8bpp)
                {
                    throw new System.Exception("Mask image must be of type PixelFormat.Gray_8bpp");
                }
            }

            PixelFormat srcFormat = srcImage.PixelFormat;
            PixelFormat dstFormat = dstImage.PixelFormat;

            System.IntPtr srcBuffer  = srcImage.ImageData;
            System.IntPtr dstBuffer  = dstImage.ImageData;
            System.IntPtr maskBuffer = (maskImage != null) ? maskImage.ImageData : System.IntPtr.Zero;
            unsafe
            {
                int   srcBytesPerPixel  = PixelFormatHelper.GetBytesPerPixel(srcFormat);
                int   dstBytesPerPixel  = PixelFormatHelper.GetBytesPerPixel(dstFormat);
                int   maskBytesPerPixel = PixelFormatHelper.GetBytesPerPixel(PixelFormat.Gray_8bpp);
                byte *srcRow            = (byte *)srcBuffer.ToPointer() + (srcRect.Y * srcImage.Stride) + (srcRect.X * srcBytesPerPixel);
                byte *dstRow            = (byte *)dstBuffer.ToPointer() + (dstRect.Y * dstImage.Stride) + (dstRect.X * dstBytesPerPixel);
                byte *maskRow           = null;
                if (maskImage != null)
                {
                    maskRow = (byte *)maskBuffer.ToPointer() + (srcRect.Y * maskImage.Stride) + (srcRect.X * maskBytesPerPixel);
                }

                for (int i = 0; i < srcRect.Height; i++)
                {
                    byte *srcCol  = srcRow;
                    byte *dstCol  = dstRow;
                    byte *maskCol = maskRow;
                    for (int j = 0; j < srcRect.Width; j++)
                    {
                        bool copyPixel = true;
                        if (maskImage != null)
                        {
                            if (*maskCol == 0)
                            {
                                copyPixel = false;
                            }
                        }

                        if (copyPixel)
                        {
                            int red   = 0;
                            int green = 0;
                            int blue  = 0;
                            int alpha = 255;
                            switch (srcFormat)
                            {
                            case PixelFormat.Gray_8bpp:
                                red = green = blue = srcCol[0];
                                break;

                            case PixelFormat.Gray_16bpp:
                                red = green = blue = ((ushort *)srcCol)[0];
                                break;

                            case PixelFormat.BGR_24bpp:
                                blue  = srcCol[0];
                                green = srcCol[1];
                                red   = srcCol[2];
                                break;

                            case PixelFormat.BGRX_32bpp:
                                blue  = srcCol[0];
                                green = srcCol[1];
                                red   = srcCol[2];
                                break;

                            case PixelFormat.BGRA_32bpp:
                                blue  = srcCol[0];
                                green = srcCol[1];
                                red   = srcCol[2];
                                alpha = srcCol[3];
                                break;

                            case PixelFormat.RGBA_64bpp:
                                red   = ((ushort *)srcCol)[0];
                                green = ((ushort *)srcCol)[1];
                                blue  = ((ushort *)srcCol)[2];
                                alpha = ((ushort *)srcCol)[3];
                                break;
                            }

                            switch (dstFormat)
                            {
                            case PixelFormat.Gray_8bpp:
                                dstCol[0] = Image.Rgb2Gray((byte)red, (byte)green, (byte)blue);
                                break;

                            case PixelFormat.Gray_16bpp:
                                ((ushort *)dstCol)[0] = Image.Rgb2Gray((ushort)red, (ushort)green, (ushort)blue);
                                break;

                            case PixelFormat.BGR_24bpp:
                            case PixelFormat.BGRX_32bpp:
                                dstCol[0] = (byte)blue;
                                dstCol[1] = (byte)green;
                                dstCol[2] = (byte)red;
                                break;

                            case PixelFormat.BGRA_32bpp:
                                dstCol[0] = (byte)blue;
                                dstCol[1] = (byte)green;
                                dstCol[2] = (byte)red;
                                dstCol[3] = (byte)alpha;
                                break;

                            case PixelFormat.RGBA_64bpp:
                                ((ushort *)dstCol)[0] = (ushort)red;
                                ((ushort *)dstCol)[1] = (ushort)green;
                                ((ushort *)dstCol)[2] = (ushort)blue;
                                ((ushort *)dstCol)[3] = (ushort)alpha;
                                break;
                            }
                        }

                        srcCol  += srcBytesPerPixel;
                        dstCol  += dstBytesPerPixel;
                        maskCol += maskBytesPerPixel;
                    }

                    srcRow += srcImage.Stride;
                    dstRow += dstImage.Stride;
                    if (maskImage != null)
                    {
                        maskRow += maskImage.Stride;
                    }
                }
            }
        }
示例#3
0
        /// <summary>
        /// Performs per channel thresholding on the image
        /// </summary>
        /// <param name="image">Image to be thresholded</param>
        /// <param name="threshold">Threshold value</param>
        /// <param name="maxvalue">Maximum value</param>
        /// <param name="type">Type of thresholding to perform</param>
        /// <returns>The thresholded image</returns>
        public static Shared <Image> Threshold(this Image image, int threshold, int maxvalue, Threshold type)
        {
            Shared <Image> dstImage = ImagePool.GetOrCreate(image.Width, image.Height, image.PixelFormat);

            unsafe
            {
                int   bytesPerPixel = PixelFormatHelper.GetBytesPerPixel(image.PixelFormat);
                byte *srcRow        = (byte *)image.ImageData.ToPointer();
                byte *dstRow        = (byte *)dstImage.Resource.ImageData.ToPointer();
                for (int i = 0; i < image.Height; i++)
                {
                    byte *srcCol = srcRow;
                    byte *dstCol = dstRow;
                    for (int j = 0; j < image.Width; j++)
                    {
                        int r = 0, g = 0, b = 0, a = 0;
                        switch (image.PixelFormat)
                        {
                        case PixelFormat.BGRA_32bpp:
                            b = srcCol[0];
                            g = srcCol[1];
                            r = srcCol[2];
                            a = srcCol[3];
                            break;

                        case PixelFormat.BGRX_32bpp:
                            b = srcCol[0];
                            g = srcCol[1];
                            r = srcCol[2];
                            break;

                        case PixelFormat.BGR_24bpp:
                            b = srcCol[0];
                            g = srcCol[1];
                            r = srcCol[2];
                            break;

                        case PixelFormat.Gray_16bpp:
                            r = g = b = a = ((ushort *)srcCol)[0];
                            break;

                        case PixelFormat.Gray_8bpp:
                            r = g = b = a = srcCol[0];
                            break;

                        case PixelFormat.RGBA_64bpp:
                            r = ((ushort *)srcCol)[0];
                            g = ((ushort *)srcCol)[1];
                            b = ((ushort *)srcCol)[2];
                            a = ((ushort *)srcCol)[3];
                            break;

                        default:
                            break;
                        }

                        switch (type)
                        {
                        case Imaging.Threshold.Binary:
                            r = (r > threshold) ? maxvalue : 0;
                            g = (g > threshold) ? maxvalue : 0;
                            b = (b > threshold) ? maxvalue : 0;
                            a = (a > threshold) ? maxvalue : 0;
                            break;

                        case Imaging.Threshold.BinaryInv:
                            r = (r > threshold) ? 0 : maxvalue;
                            g = (g > threshold) ? 0 : maxvalue;
                            b = (b > threshold) ? 0 : maxvalue;
                            a = (a > threshold) ? 0 : maxvalue;
                            break;

                        case Imaging.Threshold.Truncate:
                            r = (r > threshold) ? threshold : r;
                            g = (g > threshold) ? threshold : g;
                            b = (b > threshold) ? threshold : b;
                            a = (a > threshold) ? threshold : a;
                            break;

                        case Imaging.Threshold.ToZero:
                            r = (r > threshold) ? r : 0;
                            g = (g > threshold) ? g : 0;
                            b = (b > threshold) ? b : 0;
                            a = (a > threshold) ? a : 0;
                            break;

                        case Imaging.Threshold.ToZeroInv:
                            r = (r > threshold) ? 0 : r;
                            g = (g > threshold) ? 0 : g;
                            b = (b > threshold) ? 0 : b;
                            a = (a > threshold) ? 0 : a;
                            break;
                        }

                        switch (image.PixelFormat)
                        {
                        case PixelFormat.BGRA_32bpp:
                            dstCol[0] = (byte)b;
                            dstCol[1] = (byte)g;
                            dstCol[2] = (byte)r;
                            dstCol[3] = (byte)a;
                            break;

                        case PixelFormat.BGRX_32bpp:
                            dstCol[0] = (byte)b;
                            dstCol[1] = (byte)g;
                            dstCol[2] = (byte)r;
                            break;

                        case PixelFormat.BGR_24bpp:
                            dstCol[0] = (byte)b;
                            dstCol[1] = (byte)g;
                            dstCol[2] = (byte)r;
                            break;

                        case PixelFormat.Gray_16bpp:
                            ((ushort *)srcCol)[0] = (ushort)r;
                            break;

                        case PixelFormat.Gray_8bpp:
                            srcCol[0] = (byte)r;
                            break;

                        case PixelFormat.RGBA_64bpp:
                            ((ushort *)srcCol)[0] = (ushort)r;
                            ((ushort *)srcCol)[1] = (ushort)g;
                            ((ushort *)srcCol)[2] = (ushort)b;
                            ((ushort *)srcCol)[3] = (ushort)a;
                            break;

                        default:
                            break;
                        }

                        srcCol += bytesPerPixel;
                        dstCol += bytesPerPixel;
                    }

                    srcRow += image.Stride;
                    dstRow += dstImage.Resource.Stride;
                }
            }

            return(dstImage);
        }
示例#4
0
        /// <summary>
        /// Rotates an image
        /// </summary>
        /// <param name="image">Image to rotate</param>
        /// <param name="angleInDegrees">Number of degrees to rotate in counter clockwise direction</param>
        /// <param name="mode">Pixel resampling method</param>
        /// <returns>Rotated image</returns>
        public static Shared <Image> Rotate(this Image image, float angleInDegrees, SamplingMode mode)
        {
            float ca   = (float)System.Math.Cos(angleInDegrees * System.Math.PI / 180.0f);
            float sa   = (float)System.Math.Sin(angleInDegrees * System.Math.PI / 180.0f);
            float minx = 0.0f;
            float miny = 0.0f;
            float maxx = 0.0f;
            float maxy = 0.0f;
            float x    = image.Width - 1;
            float y    = 0.0f;
            float nx   = (x * ca) - (y * sa);
            float ny   = (x * sa) + (y * ca);

            if (nx < minx)
            {
                minx = nx;
            }

            if (nx > maxx)
            {
                maxx = nx;
            }

            if (ny < miny)
            {
                miny = ny;
            }

            if (ny > maxy)
            {
                maxy = ny;
            }

            x  = image.Width - 1;
            y  = image.Height - 1;
            nx = (x * ca) - (y * sa);
            ny = (x * sa) + (y * ca);
            if (nx < minx)
            {
                minx = nx;
            }

            if (nx > maxx)
            {
                maxx = nx;
            }

            if (ny < miny)
            {
                miny = ny;
            }

            if (ny > maxy)
            {
                maxy = ny;
            }

            x  = 0.0f;
            y  = image.Height - 1;
            nx = (x * ca) - (y * sa);
            ny = (x * sa) + (y * ca);
            if (nx < minx)
            {
                minx = nx;
            }

            if (nx > maxx)
            {
                maxx = nx;
            }

            if (ny < miny)
            {
                miny = ny;
            }

            if (ny > maxy)
            {
                maxy = ny;
            }

            int dstWidth  = (int)(maxx - minx + 1);
            int dstHeight = (int)(maxy - miny + 1);
            var bitmap    = new Bitmap(dstWidth, dstHeight);
            var graphics  = Graphics.FromImage(bitmap);

            graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
            switch (mode)
            {
            case SamplingMode.Point:
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                graphics.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                graphics.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
                graphics.PixelOffsetMode    = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
                break;

            case SamplingMode.Bilinear:
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
                graphics.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                graphics.PixelOffsetMode    = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                break;

            case SamplingMode.Bicubic:
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                graphics.PixelOffsetMode    = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                break;
            }

            graphics.TranslateTransform(-minx, -miny);
            graphics.RotateTransform(angleInDegrees);
            graphics.DrawImage(image.ToManagedImage(), new Point(0, 0));
            return(ImagePool.GetOrCreate(bitmap));
        }