Beispiel #1
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));
        }
Beispiel #2
0
        /// <summary>
        /// Flips an image along a specified axis
        /// </summary>
        /// <param name="image">Image to flip</param>
        /// <param name="mode">Axis along which to flip</param>
        /// <returns>A new flipped image</returns>
        public static Shared <Image> Flip(this Image image, FlipMode mode)
        {
            if (image.PixelFormat == PixelFormat.Gray_16bpp)
            {
                // We can't handle this through GDI.
                Shared <Image> dstImage = ImagePool.GetOrCreate(image.Width, image.Height, image.PixelFormat);
                unsafe
                {
                    int   srcBytesPerPixel = PixelFormatHelper.GetBytesPerPixel(image.PixelFormat);
                    int   dstBytesPerPixel = PixelFormatHelper.GetBytesPerPixel(dstImage.Resource.PixelFormat);
                    byte *srcRow           = (byte *)image.ImageData.ToPointer();
                    byte *dstRow           = (byte *)dstImage.Resource.ImageData.ToPointer();
                    int   ystep            = dstImage.Resource.Stride;
                    if (mode == FlipMode.AlongHorizontalAxis)
                    {
                        dstRow += dstImage.Resource.Stride * (image.Height - 1);
                        ystep   = -dstImage.Resource.Stride;
                    }

                    int xstep   = dstBytesPerPixel;
                    int xoffset = 0;
                    if (mode == FlipMode.AlongVerticalAxis)
                    {
                        xoffset = dstBytesPerPixel * (dstImage.Resource.Width - 1);
                        xstep   = -dstBytesPerPixel;
                    }

                    for (int i = 0; i < image.Height; i++)
                    {
                        byte *srcCol = srcRow;
                        byte *dstCol = dstRow + xoffset;
                        for (int j = 0; j < image.Width; j++)
                        {
                            ((ushort *)dstCol)[0] = ((ushort *)srcCol)[0];
                            srcCol += srcBytesPerPixel;
                            dstCol += xstep;
                        }

                        srcRow += image.Stride;
                        dstRow += ystep;
                    }
                }

                return(dstImage);
            }
            else
            {
                var bitmap   = new Bitmap(image.Width, image.Height);
                var graphics = Graphics.FromImage(bitmap);
                switch (mode)
                {
                case FlipMode.AlongHorizontalAxis:
                    graphics.TranslateTransform(0.0f, image.Height - 1);
                    graphics.ScaleTransform(1.0f, -1.0f);
                    break;

                case FlipMode.AlongVerticalAxis:
                    graphics.TranslateTransform(image.Width - 1, 0.0f);
                    graphics.ScaleTransform(-1.0f, 1.0f);
                    break;
                }

                graphics.DrawImage(image.ToManagedImage(), new Point(0, 0));
                return(ImagePool.GetOrCreate(bitmap));
            }
        }
Beispiel #3
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);
        }
Beispiel #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ImageTransformer"/> class.
 /// </summary>
 /// <param name="pipeline">The pipeline to add the component to.</param>
 /// <param name="transformer">Function for transforming the source image.</param>
 /// <param name="pixelFormat">Pixel format for destination image.</param>
 /// <param name="sharedImageAllocator ">Optional image allocator for creating new shared image.</param>
 /// <param name="name">An optional name for the component.</param>
 public ImageTransformer(
     Pipeline pipeline,
     TransformDelegate transformer,
     PixelFormat pixelFormat,
     Func <int, int, PixelFormat, Shared <Image> > sharedImageAllocator = null,
     string name = nameof(ImageTransformer))
     : base(pipeline, name)
 {
     this.transformer          = transformer;
     this.pixelFormat          = pixelFormat;
     this.sharedImageAllocator = sharedImageAllocator ?? ((width, height, pixelFormat) => ImagePool.GetOrCreate(width, height, pixelFormat));
 }
Beispiel #5
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);
        }