Example #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ToPixelFormat"/> class.
 /// </summary>
 /// <param name="pipeline">The pipeline.</param>
 /// <param name="pixelFormat">The pixel format to convert to.</param>
 /// <param name="sharedImageAllocator ">Optional image allocator for creating new shared image.</param>
 internal ToPixelFormat(Pipeline pipeline, PixelFormat pixelFormat, System.Func <int, int, PixelFormat, Shared <Image> > sharedImageAllocator = null)
     : base(pipeline)
 {
     this.pixelFormat = pixelFormat;
     sharedImageAllocator ??= (width, height, pixelFormat) => ImagePool.GetOrCreate(width, height, pixelFormat);
     this.sharedImageAllocator = sharedImageAllocator;
 }
Example #2
0
        /// <inheritdoc/>
        protected override void Receive(Shared <EncodedImage> sharedEncodedImage, Envelope envelope)
        {
            if (sharedEncodedImage == null || sharedEncodedImage.Resource == null)
            {
                this.Out.Post(null, envelope.OriginatingTime);
                return;
            }

            // The code below maintains back-compatibility with encoded images which did not store the pixel format
            // on the instance, but only in the stream. If the pixel format is unknown, we call upon the decoder to
            // retrieve the pixel format. This might be less performant, but enables decoding in the right format
            // even from older versions of encoded images.
            var pixelFormat = sharedEncodedImage.Resource.PixelFormat == PixelFormat.Undefined ?
                              this.decoder.GetPixelFormat(sharedEncodedImage.Resource.ToStream()) : sharedEncodedImage.Resource.PixelFormat;

            // If the decoder does not return a valid pixel format, we throw an exception.
            if (pixelFormat == PixelFormat.Undefined)
            {
                throw new ArgumentException("The encoded image does not contain a supported pixel format.");
            }

            using var sharedImage = ImagePool.GetOrCreate(
                      sharedEncodedImage.Resource.Width, sharedEncodedImage.Resource.Height, pixelFormat);
            sharedImage.Resource.DecodeFrom(sharedEncodedImage.Resource, this.decoder);
            this.Out.Post(sharedImage, envelope.OriginatingTime);
        }
Example #3
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>
 public ImageTransformer(Pipeline pipeline, TransformDelegate transformer, PixelFormat pixelFormat, System.Func <int, int, PixelFormat, Shared <Image> > sharedImageAllocator = null)
     : base(pipeline)
 {
     this.transformer = transformer;
     this.pixelFormat = pixelFormat;
     sharedImageAllocator ??= (width, height, pixelFormat) => ImagePool.GetOrCreate(width, height, pixelFormat);
     this.sharedImageAllocator = sharedImageAllocator;
 }
Example #4
0
 /// <summary>
 /// Pipeline callback method for decoding a sample.
 /// </summary>
 /// <param name="encodedImage">Encoded image to decode.</param>
 /// <param name="e">Pipeline information about the sample.</param>
 protected override void Receive(Shared <EncodedImage> encodedImage, Envelope e)
 {
     using (var image = ImagePool.GetOrCreate(encodedImage.Resource.Width, encodedImage.Resource.Height, Imaging.PixelFormat.BGR_24bpp))
     {
         DecodeTo(encodedImage.Resource, image.Resource);
         this.Out.Post(image, e.OriginatingTime);
     }
 }
Example #5
0
 /// <summary>
 /// Pipeline callback for processing this component
 /// </summary>
 /// <param name="sharedImage">Image to transform</param>
 /// <param name="e">Pipeline sample information</param>
 protected override void Receive(Shared <Image> sharedImage, Envelope e)
 {
     using (var psiImageDest = ImagePool.GetOrCreate(sharedImage.Resource.Width, sharedImage.Resource.Height, this.pixelFormat))
     {
         this.transformer(sharedImage.Resource, psiImageDest.Resource);
         this.Out.Post(psiImageDest, e.OriginatingTime);
     }
 }
Example #6
0
        /// <summary>
        /// Inverts an image.
        /// </summary>
        /// <param name="image">Image to invert</param>
        /// <returns>Returns the inverted image</returns>
        public static Shared <Image> Invert(this Image image)
        {
            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();
                for (int i = 0; i < image.Height; i++)
                {
                    byte *srcCol = srcRow;
                    byte *dstCol = dstRow;
                    for (int j = 0; j < image.Width; j++)
                    {
                        switch (image.PixelFormat)
                        {
                        case PixelFormat.Gray_8bpp:
                            dstCol[0] = (byte)(255 - srcCol[0]);
                            break;

                        case PixelFormat.Gray_16bpp:
                            ((ushort *)dstCol)[0] = (byte)(65535 - srcCol[0]);
                            break;

                        case PixelFormat.BGR_24bpp:
                            dstCol[0] = (byte)(255 - srcCol[0]);
                            dstCol[1] = (byte)(255 - srcCol[1]);
                            dstCol[2] = (byte)(255 - srcCol[2]);
                            break;

                        case PixelFormat.BGRX_32bpp:
                            dstCol[0] = (byte)(255 - srcCol[0]);
                            dstCol[1] = (byte)(255 - srcCol[1]);
                            dstCol[2] = (byte)(255 - srcCol[2]);
                            break;

                        case PixelFormat.BGRA_32bpp:
                            dstCol[0] = (byte)(255 - srcCol[0]);
                            dstCol[1] = (byte)(255 - srcCol[1]);
                            dstCol[2] = (byte)(255 - srcCol[2]);
                            dstCol[3] = (byte)(255 - srcCol[3]);
                            break;
                        }

                        srcCol += srcBytesPerPixel;
                        dstCol += dstBytesPerPixel;
                    }

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

            return(dstImage);
        }
Example #7
0
        /// <summary>
        /// Resizes an image by the specified scale factors using the specified sampling mode.
        /// </summary>
        /// <param name="image">Image to resize.</param>
        /// <param name="scaleX">Scale factor to apply in X direction.</param>
        /// <param name="scaleY">Scale factor to apply in Y direction.</param>
        /// <param name="mode">Sampling mode for sampling of pixels.</param>
        /// <returns>Returns a new image scaled by the specified scale factors.</returns>
        public static Shared <Image> Scale(this Image image, float scaleX, float scaleY, SamplingMode mode)
        {
            if (scaleX == 0.0 || scaleY == 0.0)
            {
                throw new System.Exception("Unexpected scale factors");
            }

            if (image.PixelFormat == PixelFormat.Gray_16bpp)
            {
                throw new System.NotSupportedException(
                          "Scaling 16bpp images is not currently supported. " +
                          "Convert to a supported format such as color or 8bpp grayscale first.");
            }

            int dstWidth  = (int)(image.Width * scaleX);
            int dstHeight = (int)(image.Height * scaleY);

            using (var bitmap = new Bitmap(dstWidth, dstHeight))
            {
                using (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.ScaleTransform(scaleX, scaleY);

                    using (var managedimg = image.ToManagedImage())
                    {
                        graphics.DrawImage(managedimg, new Point(0, 0));
                    }

                    return(ImagePool.GetOrCreate(bitmap));
                }
            }
        }
Example #8
0
        /// <summary>
        /// Given an serialization stream, this method will decompress
        /// an image from the stream and return the image via 'target'
        /// </summary>
        /// <param name="reader">Stream to read compressed image from</param>
        /// <param name="target">Returns the decompressed image</param>
        /// <param name="context">Serialization context</param>
        public void Deserialize(BufferReader reader, ref Image target, SerializationContext context)
        {
            Shared <EncodedImage> encodedImage = null;

            Serializer.Deserialize(reader, ref encodedImage, context);
            using (var image = ImagePool.GetOrCreate(encodedImage.Resource.Width, encodedImage.Resource.Height, Imaging.PixelFormat.BGR_24bpp))
            {
                encodedImage.Resource.DecodeTo(image.Resource);
                target = image.Resource.DeepClone();
            }
        }
Example #9
0
        /// <inheritdoc/>
        public void Deserialize(BufferReader reader, ref Image image, SerializationContext context)
        {
            Shared <EncodedImage> sharedEncodedImage = null;

            Serializer.Deserialize(reader, ref sharedEncodedImage, context);
            using var sharedImage = ImagePool.GetOrCreate(
                      sharedEncodedImage.Resource.Width, sharedEncodedImage.Resource.Height, sharedEncodedImage.Resource.PixelFormat);
            sharedImage.Resource.DecodeFrom(sharedEncodedImage.Resource, this.decoder);
            image = sharedImage.Resource.DeepClone();
            sharedEncodedImage.Dispose();
        }
Example #10
0
 /// <summary>
 /// Converts a stream of depth images into a stream of <see cref="PixelFormat.Gray_16bpp"/> format images.
 /// </summary>
 /// <param name="source">A producer of depth images.</param>
 /// <param name="deliveryPolicy">An optional delivery policy.</param>
 /// <param name="sharedDepthImageAllocator ">Optional image allocator for creating new shared depth image.</param>
 /// <returns>A corresponding stream of images.</returns>
 public static IProducer <Shared <Image> > ToImage(this IProducer <Shared <DepthImage> > source, DeliveryPolicy <Shared <DepthImage> > deliveryPolicy = null, Func <int, int, Shared <Image> > sharedDepthImageAllocator = null)
 {
     sharedDepthImageAllocator ??= (width, height) => ImagePool.GetOrCreate(width, height, PixelFormat.Gray_16bpp);
     return(source.Process <Shared <DepthImage>, Shared <Image> >(
                (sharedDepthImage, envelope, emitter) =>
     {
         using var sharedImage = sharedDepthImageAllocator(sharedDepthImage.Resource.Width, sharedDepthImage.Resource.Height);
         sharedImage.Resource.CopyFrom(sharedDepthImage.Resource);
         emitter.Post(sharedImage, envelope.OriginatingTime);
     },
                deliveryPolicy));
 }
Example #11
0
        /// <summary>
        /// Pipeline callback method for decoding a sample.
        /// </summary>
        /// <param name="encodedImage">Encoded image to decode.</param>
        /// <param name="e">Pipeline information about the sample.</param>
        protected override void Receive(Shared <EncodedImage> encodedImage, Envelope e)
        {
            if (this.imagePixelFormat == PixelFormat.Undefined)
            {
                this.imagePixelFormat = GetPixelFormat(encodedImage.Resource);
            }

            using (var image = ImagePool.GetOrCreate(encodedImage.Resource.Width, encodedImage.Resource.Height, this.imagePixelFormat))
            {
                DecodeTo(encodedImage.Resource, image.Resource);
                this.Out.Post(image, e.OriginatingTime);
            }
        }
Example #12
0
        /// <summary>
        /// Creates a copy of the image cropped to the specified dimensions.
        /// </summary>
        /// <param name="left">The left of the region to crop.</param>
        /// <param name="top">The top of the region to crop.</param>
        /// <param name="width">The width of the region to crop.</param>
        /// <param name="height">The height of the region to crop.</param>
        /// <returns>The cropped image.</returns>
        public Shared <Image> Crop(int left, int top, int width, int height)
        {
            if ((left < 0) || (left > (this.width - 1)))
            {
                throw new ArgumentOutOfRangeException("left", "left is out of range");
            }

            if ((top < 0) || (top > (this.height - 1)))
            {
                throw new ArgumentOutOfRangeException("top", "top is out of range");
            }

            if ((width < 0) || ((left + width) > this.width))
            {
                throw new ArgumentOutOfRangeException("width", "width is out of range");
            }

            if ((height < 0) || ((top + height) > this.height))
            {
                throw new ArgumentOutOfRangeException("height", "height is out of range");
            }

            // Cropped image will be returned as a new image - original (this) image is not modified
            Shared <Image> croppedImage = ImagePool.GetOrCreate(width, height, this.pixelFormat);

            Debug.Assert(croppedImage.Resource.image.Data != IntPtr.Zero, "Unexpected empty image");
            unsafe
            {
                int bytesPerPixel = this.BitsPerPixel / 8;

                // Compute the number of bytes in each line of the crop region
                int copyLength = width * bytesPerPixel;

                // Start at top-left of region to crop
                byte *src = (byte *)this.image.Data.ToPointer() + (top * this.stride) + (left * bytesPerPixel);
                byte *dst = (byte *)croppedImage.Resource.image.Data.ToPointer();

                // Copy line by line
                for (int i = 0; i < height; i++)
                {
                    Buffer.MemoryCopy(src, dst, copyLength, copyLength);

                    src += this.stride;
                    dst += croppedImage.Resource.stride;
                }
            }

            return(croppedImage);
        }
Example #13
0
 /// <summary>
 /// Receiver for incoming image
 /// </summary>
 /// <param name="sharedImage">The incoming image</param>
 /// <param name="e">The message envelope for the incoming image.</param>
 protected override void Receive(Shared <Image> sharedImage, Envelope e)
 {
     // if it has the same format, shortcut the loop
     if (this.pixelFormat == sharedImage.Resource.PixelFormat)
     {
         this.Out.Post(sharedImage, e.OriginatingTime);
     }
     else
     {
         using (var image = ImagePool.GetOrCreate(sharedImage.Resource.Width, sharedImage.Resource.Height, this.pixelFormat))
         {
             sharedImage.Resource.CopyTo(image.Resource);
             this.Out.Post(image, e.OriginatingTime);
         }
     }
 }
        /// <inheritdoc/>
        public void DecodeFromStream(Stream stream, Image image)
        {
            // decode JPEG, PNG, ...
            var          decoder      = BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            BitmapSource bitmapSource = decoder.Frames[0];
            var          fmt          = bitmapSource.Format.ToPixelFormat();

            if (fmt != image.PixelFormat)
            {
                using var img = ImagePool.GetOrCreate(image.Width, image.Height, fmt);
                bitmapSource.CopyPixels(Int32Rect.Empty, img.Resource.ImageData, img.Resource.Stride * img.Resource.Height, img.Resource.Stride);
                img.Resource.CopyTo(image);
            }
            else
            {
                bitmapSource.CopyPixels(Int32Rect.Empty, image.ImageData, image.Stride * image.Height, image.Stride);
            }
        }
Example #15
0
        /// <summary>
        /// Extracts a single channel from the image and returns it as a gray scale image.
        /// </summary>
        /// <param name="image">Image to extract from</param>
        /// <param name="channel">Index of channel to extract from</param>
        /// <returns>Returns a new grayscale image containing the color from the specified channel in the original source image</returns>
        public static Shared <Image> ExtractChannel(this Image image, int channel /* 0=red, 1=green, 2=blue, 3=alpha */)
        {
            if (image.PixelFormat != PixelFormat.BGRA_32bpp &&
                image.PixelFormat != PixelFormat.BGRX_32bpp &&
                image.PixelFormat != PixelFormat.BGR_24bpp)
            {
                throw new System.Exception("Extract only supports the following pixel formats: BGRA_32bpp, BGRX_32bpp, and BGR_24bpp");
            }

            if (channel < 0 ||
                (image.PixelFormat != PixelFormat.BGR_24bpp && channel > 3) ||
                (image.PixelFormat == PixelFormat.BGR_24bpp && channel > 2))
            {
                throw new System.Exception("Unsupported channel");
            }

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

            unsafe
            {
                int   srcBytesPerPixel = PixelFormatHelper.GetBytesPerPixel(image.PixelFormat);
                int   dstBytesPerPixel = PixelFormatHelper.GetBytesPerPixel(PixelFormat.Gray_8bpp);
                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++)
                    {
                        dstCol[0] = srcCol[channel];
                        srcCol   += srcBytesPerPixel;
                        dstCol   += dstBytesPerPixel;
                    }

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

            return(dstImage);
        }
Example #16
0
        /// <summary>
        /// Resizes an image by the specified scale factors using the specified sampling mode
        /// </summary>
        /// <param name="image">Image to resize</param>
        /// <param name="xScale">Scale factor to apply in X direction</param>
        /// <param name="yScale">Scale factor to apply in Y direction</param>
        /// <param name="mode">Sampling mode for sampling of pixels</param>
        /// <returns>Returns a new image scaled by the specified scale factors</returns>
        public static Shared <Image> Scale(this Image image, float xScale, float yScale, SamplingMode mode)
        {
            if (xScale == 0.0 || yScale == 0.0)
            {
                throw new System.Exception("Unexpected scale factors");
            }

            int dstWidth  = (int)(image.Width * xScale);
            int dstHeight = (int)(image.Height * yScale);
            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.ScaleTransform(xScale, yScale);
            graphics.DrawImage(image.ToManagedImage(), new Point(0, 0));
            return(ImagePool.GetOrCreate(bitmap));
        }
Example #17
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)
        {
            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));
        }
Example #18
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);
        }
Example #19
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));
        }
Example #20
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));
            }
        }
Example #21
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);
        }
Example #22
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));
 }