c# Image resizing to different size while preserving aspect ratio

C#Image Processingsystem.drawingImage Scaling

C# Problem Overview


I'm trying to resize an image while preserving the aspect ratio from the original image so the new image doesn't look squashed.

eg:

> Convert a 150100 image into a 150150 image.
> The extra 50 pixels of the height need to be padded with a white background color.

This is the current code I am using.

It works well for resizing but changing the aspect ratio of the original image squashes the new image.

private void resizeImage(string path, string originalFilename, 
                         int width, int height)
    {
        Image image = Image.FromFile(path + originalFilename);

        System.Drawing.Image thumbnail = new Bitmap(width, height);
        System.Drawing.Graphics graphic = 
                     System.Drawing.Graphics.FromImage(thumbnail);

        graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphic.SmoothingMode = SmoothingMode.HighQuality;
        graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
        graphic.CompositingQuality = CompositingQuality.HighQuality;

        graphic.DrawImage(image, 0, 0, width, height);

        System.Drawing.Imaging.ImageCodecInfo[] info =
                         ImageCodecInfo.GetImageEncoders();
        EncoderParameters encoderParameters;
        encoderParameters = new EncoderParameters(1);
        encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
                         100L);            
        thumbnail.Save(path + width + "." + originalFilename, info[1], 
                         encoderParameters);
    }

EDIT: I'd like to have the image padded instead of cropped

C# Solutions


Solution 1 - C#

This should do it.

private void resizeImage(string path, string originalFilename, 
                     /* note changed names */
                     int canvasWidth, int canvasHeight, 
                     /* new */
                     int originalWidth, int originalHeight)
{
    Image image = Image.FromFile(path + originalFilename);

    System.Drawing.Image thumbnail = 
        new Bitmap(canvasWidth, canvasHeight); // changed parm names
    System.Drawing.Graphics graphic = 
                 System.Drawing.Graphics.FromImage(thumbnail);

    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graphic.SmoothingMode = SmoothingMode.HighQuality;
    graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
    graphic.CompositingQuality = CompositingQuality.HighQuality;

    /* ------------------ new code --------------- */

    // Figure out the ratio
    double ratioX = (double) canvasWidth / (double) originalWidth;
    double ratioY = (double) canvasHeight / (double) originalHeight;
    // use whichever multiplier is smaller
    double ratio = ratioX < ratioY ? ratioX : ratioY;

    // now we can get the new height and width
    int newHeight = Convert.ToInt32(originalHeight * ratio);
    int newWidth = Convert.ToInt32(originalWidth * ratio);

    // Now calculate the X,Y position of the upper-left corner 
    // (one of these will always be zero)
    int posX = Convert.ToInt32((canvasWidth - (originalWidth * ratio)) / 2);
    int posY = Convert.ToInt32((canvasHeight - (originalHeight * ratio)) / 2);

    graphic.Clear(Color.White); // white padding
    graphic.DrawImage(image, posX, posY, newWidth, newHeight);

    /* ------------- end new code ---------------- */

    System.Drawing.Imaging.ImageCodecInfo[] info =
                     ImageCodecInfo.GetImageEncoders();
    EncoderParameters encoderParameters;
    encoderParameters = new EncoderParameters(1);
    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
                     100L);            
    thumbnail.Save(path + newWidth + "." + originalFilename, info[1], 
                     encoderParameters);
}

Edited to add:

Those who want to improve this code should put it in the comments, or a new answer. Don't edit this code directly.

Solution 2 - C#

I found out how to resize AND pad the image by learning from this this CodeProject Article.

static Image FixedSize(Image imgPhoto, int Width, int Height)
    {
        int sourceWidth = imgPhoto.Width;
        int sourceHeight = imgPhoto.Height;
        int sourceX = 0;
        int sourceY = 0;
        int destX = 0;
        int destY = 0;

        float nPercent = 0;
        float nPercentW = 0;
        float nPercentH = 0;

        nPercentW = ((float)Width / (float)sourceWidth);
        nPercentH = ((float)Height / (float)sourceHeight);
        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16((Width -
                          (sourceWidth * nPercent)) / 2);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16((Height -
                          (sourceHeight * nPercent)) / 2);
        }

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);

        Bitmap bmPhoto = new Bitmap(Width, Height,
                          PixelFormat.Format24bppRgb);
        bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                         imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(Color.Red);
        grPhoto.InterpolationMode =
                InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

Solution 3 - C#

I use the following method to calculate the desired image size:

using System.Drawing;
public static Size ResizeKeepAspect(this Size src, int maxWidth, int maxHeight, bool enlarge = false)
{
    maxWidth = enlarge ? maxWidth : Math.Min(maxWidth, src.Width);
    maxHeight = enlarge ? maxHeight : Math.Min(maxHeight, src.Height);

    decimal rnd = Math.Min(maxWidth / (decimal)src.Width, maxHeight / (decimal)src.Height);
    return new Size((int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));
}

This puts the problem of aspect ratio and dimensions in a separate method.

What does the parameter bool enlarge = false ?

usually you do only shrinking of images because enlarging means quality loss - so I added this optional parameter if you want to do it anyway

Solution 4 - C#

To get a faster result, the function that obtains the size could be found in resultSize:

Size original = new Size(640, 480);

int maxSize = 100;

float percent = (new List<float> { (float)maxSize / (float)original.Width , (float)maxSize  / (float)original.Height }).Min();

Size resultSize = new Size((int)Math.Floor(original.Width * percent), (int)Math.Floor(original.Height * percent));

Uses Linq to minimize variable and recalculations, as well as unnecesary if/else statements

Solution 5 - C#

Just generalizing it down to aspect ratios and sizes, image stuff can be done outside of this function

public static d.RectangleF ScaleRect(d.RectangleF dest, d.RectangleF src, 
  bool keepWidth, bool keepHeight)  
{
    d.RectangleF destRect = new d.RectangleF();

    float sourceAspect = src.Width / src.Height;
    float destAspect = dest.Width / dest.Height;

    if (sourceAspect > destAspect)
    {
        // wider than high keep the width and scale the height
        destRect.Width = dest.Width;
        destRect.Height = dest.Width / sourceAspect;

        if (keepHeight)
        {
            float resizePerc = dest.Height / destRect.Height;
            destRect.Width = dest.Width * resizePerc;
            destRect.Height = dest.Height;
        }
    }
    else
    {
        // higher than wide – keep the height and scale the width
        destRect.Height = dest.Height;
        destRect.Width = dest.Height * sourceAspect;

        if (keepWidth)
        {
            float resizePerc = dest.Width / destRect.Width;
            destRect.Width = dest.Width;
            destRect.Height = dest.Height * resizePerc;
        }

    }

    return destRect;
}

Solution 6 - C#

I'm going to add my code here too. This code will allow you resize an image with or without the aspect ratio being enforced or to resize with padding. This is a modified version of egrunin's code.

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace ConsoleApplication1
{
	public class Program
	{
		public static void Main(string[] args)
		{
			var path = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
			ResizeImage(path, "large.jpg", path, "new.jpg", 100, 100, true, true);
		}

		/// <summary>Resizes an image to a new width and height.</summary>
		/// <param name="originalPath">The folder which holds the original image.</param>
		/// <param name="originalFileName">The file name of the original image.</param>
		/// <param name="newPath">The folder which will hold the resized image.</param>
		/// <param name="newFileName">The file name of the resized image.</param>
		/// <param name="maximumWidth">When resizing the image, this is the maximum width to resize the image to.</param>
		/// <param name="maximumHeight">When resizing the image, this is the maximum height to resize the image to.</param>
		/// <param name="enforceRatio">Indicates whether to keep the width/height ratio aspect or not. If set to false, images with an unequal width and height will be distorted and padding is disregarded. If set to true, the width/height ratio aspect is maintained and distortion does not occur.</param>
		/// <param name="addPadding">Indicates whether fill the smaller dimension of the image with a white background. If set to true, the white padding fills the smaller dimension until it reach the specified max width or height. This is used for maintaining a 1:1 ratio if the max width and height are the same.</param>
		private static void ResizeImage(string originalPath, string originalFileName, string newPath, string newFileName, int maximumWidth, int maximumHeight, bool enforceRatio, bool addPadding)
		{
			var image = Image.FromFile(originalPath + "\\" + originalFileName);
			var imageEncoders = ImageCodecInfo.GetImageEncoders();
			EncoderParameters encoderParameters = new EncoderParameters(1);
			encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
			var canvasWidth = maximumWidth;
			var canvasHeight = maximumHeight;
			var newImageWidth = maximumWidth;
			var newImageHeight = maximumHeight;
			var xPosition = 0;
			var yPosition = 0;


			if (enforceRatio)
			{
				var ratioX = maximumWidth / (double)image.Width;
				var ratioY = maximumHeight / (double)image.Height;
				var ratio = ratioX < ratioY ? ratioX : ratioY;
				newImageHeight = (int)(image.Height * ratio);
				newImageWidth = (int)(image.Width * ratio);

				if (addPadding)
				{
					xPosition = (int)((maximumWidth - (image.Width * ratio)) / 2);
					yPosition = (int)((maximumHeight - (image.Height * ratio)) / 2);
				}
				else
				{
					canvasWidth = newImageWidth;
					canvasHeight = newImageHeight;					
				}
			}

			var thumbnail = new Bitmap(canvasWidth, canvasHeight);
			var graphic = Graphics.FromImage(thumbnail);

			if (enforceRatio && addPadding)
			{
				graphic.Clear(Color.White);
			}

			graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
			graphic.SmoothingMode = SmoothingMode.HighQuality;
			graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
			graphic.CompositingQuality = CompositingQuality.HighQuality;
			graphic.DrawImage(image, xPosition, yPosition, newImageWidth, newImageHeight);

			thumbnail.Save(newPath + "\\" + newFileName, imageEncoders[1], encoderParameters);
		}
	}
}

Solution 7 - C#

Here's a less specific extension method that works with Image rather than doing the loading and saving for you. It also allows you to specify interpolation method and correctly renders edges when you use NearestNeighbour interpolation.

The image will be rendered within the bounds of the area you specify so you always know your output width and height. e.g:

Scaled within bounds

namespace YourApp
{
    #region Namespaces
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Drawing.Drawing2D;
    #endregion

    /// <summary>Generic helper functions related to graphics.</summary>
    public static class ImageExtensions
    {
        /// <summary>Resizes an image to a new width and height value.</summary>
        /// <param name="image">The image to resize.</param>
        /// <param name="newWidth">The width of the new image.</param>
        /// <param name="newHeight">The height of the new image.</param>
        /// <param name="mode">Interpolation mode.</param>
        /// <param name="maintainAspectRatio">If true, the image is centered in the middle of the returned image, maintaining the aspect ratio of the original image.</param>
        /// <returns>The new image. The old image is unaffected.</returns>
        public static Image ResizeImage(this Image image, int newWidth, int newHeight, InterpolationMode mode = InterpolationMode.Default, bool maintainAspectRatio = false)
        {
            Bitmap output = new Bitmap(newWidth, newHeight, image.PixelFormat);

            using (Graphics gfx = Graphics.FromImage(output))
            {
                gfx.Clear(Color.FromArgb(0, 0, 0, 0));
                gfx.InterpolationMode = mode;
                if (mode == InterpolationMode.NearestNeighbor)
                {
                    gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    gfx.SmoothingMode = SmoothingMode.HighQuality;
                }

                double ratioW = (double)newWidth / (double)image.Width;
                double ratioH = (double)newHeight / (double)image.Height;
                double ratio = ratioW < ratioH ? ratioW : ratioH;
                int insideWidth = (int)(image.Width * ratio);
                int insideHeight = (int)(image.Height * ratio);

                gfx.DrawImage(image, new Rectangle((newWidth / 2) - (insideWidth / 2), (newHeight / 2) - (insideHeight / 2), insideWidth, insideHeight));
            }

            return output;
        }
	}
}

Solution 8 - C#

// This allows us to resize the image. It prevents skewed images and 
// also vertically long images caused by trying to maintain the aspect 
// ratio on images who's height is larger than their width

public void ResizeImage(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)

{
	System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);

	// Prevent using images internal thumbnail
	FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
	FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);

	if (OnlyResizeIfWider)
	{
		if (FullsizeImage.Width <= NewWidth)
		{
			NewWidth = FullsizeImage.Width;
		}
	}

	int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
	if (NewHeight > MaxHeight)
	{
		// Resize with height instead
		NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
		NewHeight = MaxHeight;
	}

	System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);

	// Clear handle to original file so that we can overwrite it if necessary
	FullsizeImage.Dispose();

	// Save resized picture
	NewImage.Save(NewFile);
}

Solution 9 - C#

Note: this code resizes and removes everything outside the aspect ratio instead of padding it..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace MyPhotos.Common
{
    public class ThumbCreator
    {

        public enum VerticalAlign
        {
            Top,
            Middle,
            Bottom
        }

        public enum HorizontalAlign
        {
            Left,
            Middle,
            Right
        }

        public void Convert(string sourceFile, string targetFile, ImageFormat targetFormat, int height, int width, VerticalAlign valign, HorizontalAlign halign)
        {
            using (Image img = Image.FromFile(sourceFile))
            {
                using (Image targetImg = Convert(img, height, width, valign, halign))
                {
                    string directory = Path.GetDirectoryName(targetFile);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
                    if (targetFormat == ImageFormat.Jpeg)
                    {
                        SaveJpeg(targetFile, targetImg, 100);
                    }
                    else
                    {
                        targetImg.Save(targetFile, targetFormat);
                    }
                }
            }
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        // <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        public static void SaveJpeg(string path, Image img, int quality)
        {
            if (quality < 0 || quality > 100)
                throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");


            // Encoder parameter for image quality 
            EncoderParameter qualityParam =
                new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats 
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec 
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }

        public Image Convert(Image img, int height, int width, VerticalAlign valign, HorizontalAlign halign)
        {
            Bitmap result = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(result))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                float ratio = (float)height / (float)img.Height;
                int temp = (int)((float)img.Width * ratio);
                if (temp == width)
                {
                    //no corrections are needed!
                    g.DrawImage(img, 0, 0, width, height);
                    return result;
                }
                else if (temp > width)
                {
                    //den e för bred!
                    int overFlow = (temp - width);
                    if (halign == HorizontalAlign.Middle)
                    {
                        g.DrawImage(img, 0 - overFlow / 2, 0, temp, height);
                    }
                    else if (halign == HorizontalAlign.Left)
                    {
                        g.DrawImage(img, 0, 0, temp, height);
                    }
                    else if (halign == HorizontalAlign.Right)
                    {
                        g.DrawImage(img, -overFlow, 0, temp, height);
                    }
                }
                else
                {
                    //den e för hög!
                    ratio = (float)width / (float)img.Width;
                    temp = (int)((float)img.Height * ratio);
                    int overFlow = (temp - height);
                    if (valign == VerticalAlign.Top)
                    {
                        g.DrawImage(img, 0, 0, width, temp);
                    }
                    else if (valign == VerticalAlign.Middle)
                    {
                        g.DrawImage(img, 0, -overFlow / 2, width, temp);
                    }
                    else if (valign == VerticalAlign.Bottom)
                    {
                        g.DrawImage(img, 0, -overFlow, width, temp);
                    }
                }
            }
            return result;
        }
    }
}

Solution 10 - C#

I created a extension method that is much simpiler than the answers that are posted. and the aspect ratio is applied without cropping the image.

public static Image Resize(this Image image, int width, int height) {
     var scale = Math.Min(height / (float)image.Height, width / (float)image.Width);
     return image.GetThumbnailImage((int)(image.Width * scale), (int)(image.Height * scale), () => false, IntPtr.Zero);
}

Example usage:

using (var img = Image.FromFile(pathToOriginalImage)) {
	using (var thumbnail = img.Resize(60, 60)){
        // Here you can do whatever you need to do with thumnail
	}
}

Solution 11 - C#

Maintain aspect Ration and eliminate letterbox and Pillarbox.

static Image FixedSize(Image imgPhoto, int Width, int Height)
	{
		int sourceWidth = imgPhoto.Width;
		int sourceHeight = imgPhoto.Height;
		int X = 0;
		int Y = 0;

		float nPercent = 0;
		float nPercentW = 0;
		float nPercentH = 0;

		nPercentW = ((float)Width / (float)sourceWidth);
		nPercentH = ((float)Height / (float)sourceHeight);
		if (nPercentH < nPercentW)
		{
			nPercent = nPercentH;
		}
		else
		{
			nPercent = nPercentW;
		}

		int destWidth = (int)(sourceWidth * nPercent);
		int destHeight = (int)(sourceHeight * nPercent);

		Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);

		bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
										 imgPhoto.VerticalResolution);

		Graphics grPhoto = Graphics.FromImage(bmPhoto);

		grPhoto.DrawImage(imgPhoto,
				new Rectangle(X, Y, destWidth, destHeight),
				new Rectangle(X, Y, sourceWidth, sourceHeight),
				GraphicsUnit.Pixel);

		grPhoto.Dispose();
		return bmPhoto;
	}

Solution 12 - C#

public static void resizeImage_n_save(Stream sourcePath, string targetPath, int requiredSize)
    {
        using (var image = System.Drawing.Image.FromStream(sourcePath))
        {
            double ratio = 0;

            var newWidth = 0;
            var newHeight = 0;
            double w = Convert.ToInt32(image.Width);
            double h = Convert.ToInt32(image.Height);
            if (w > h)
            {
                ratio = h / w * 100;
                newWidth = requiredSize;
                newHeight = Convert.ToInt32(requiredSize * ratio / 100);
            }
            else
            {
                ratio = w / h * 100;
                newHeight = requiredSize;
                newWidth = Convert.ToInt32(requiredSize * ratio / 100);
            }
            
            //   var newWidth = (int)(image.Width * scaleFactor);
            // var newHeight = (int)(image.Height * scaleFactor);
            var thumbnailImg = new Bitmap(newWidth, newHeight);
            var thumbGraph = Graphics.FromImage(thumbnailImg);
            thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
            thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
            thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
            var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);

            thumbGraph.DrawImage(image, imageRectangle);
            thumbnailImg.Save(targetPath, image.RawFormat);

            //var img = FixedSize(image, requiredSize, requiredSize);
            //img.Save(targetPath, image.RawFormat);

        }
    }

Solution 13 - C#

I just wrote this cos none of the answers already here were simple enough. You can replace the hardcoded 128 for whatever you want or base them off the size of the original image. All i wanted was to rescale the image into a 128x128 image, keeping the aspect ratio and centering the result in the new image.

    private Bitmap CreateLargeIconForImage(Bitmap src)
    {
        Bitmap bmp = new Bitmap(128, 128);
        Graphics g = Graphics.FromImage(bmp);

        float scale = Math.Max((float)src.Width / 128.0f, (float)src.Height / 128.0f);
        PointF p = new PointF(128.0f - ((float)src.Width / scale), 128.0f - ((float)src.Height / scale));
        SizeF size = new SizeF((float)src.Width / scale, (float)src.Height / scale);

        g.DrawImage(src, new RectangleF(p, size));

        return bmp;
    }

Solution 14 - C#

I know this is an older thread. However, this is the first result in a Google search on the topic. None of the answers fit my requirement. So, here's a solution I put together by understanding the older solutions, but limiting the result image size to the most suitable height and width.

        double ratioW = (double)desiredWidthPixels / (double)originalImage.Width;
        double ratioH = (double)desiredHeightPixels / (double)originalImage.Height;
        double ratio = ratioW < ratioH ? ratioW : ratioH;
        int suitableWidth = (int)(originalImage.Width * ratio);
        int suitableHeight = (int)(originalImage.Height * ratio);

        var resizedPhoto = new Bitmap((int)suitableWidth, (int)suitableHeight);
        var graphicsSurface = Graphics.FromImage(resizedPhoto);
        graphicsSurface.DrawImage(originalImage, new RectangleF(new PointF(0,0), new SizeF(suitableWidth, suitableHeight)));

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionsf.View Question on Stackoverflow
Solution 1 - C#egruninView Answer on Stackoverflow
Solution 2 - C#sf.View Answer on Stackoverflow
Solution 3 - C#fuboView Answer on Stackoverflow
Solution 4 - C#ciosoriogView Answer on Stackoverflow
Solution 5 - C#jaelpanzerView Answer on Stackoverflow
Solution 6 - C#HalcyonView Answer on Stackoverflow
Solution 7 - C#RobView Answer on Stackoverflow
Solution 8 - C#user195488View Answer on Stackoverflow
Solution 9 - C#PeterView Answer on Stackoverflow
Solution 10 - C#MikeView Answer on Stackoverflow
Solution 11 - C#user4849858View Answer on Stackoverflow
Solution 12 - C#satyenderView Answer on Stackoverflow
Solution 13 - C#adhd engineeringView Answer on Stackoverflow
Solution 14 - C#Nalin JayasuriyaView Answer on Stackoverflow