Resize image preserving aspect ratio in C#

The aspect ratio of an image describes the proportional relationship between its width and its height. For an x:y aspect ratio, if the width is divided into x units of equal length and the height is measured using this same length unit, the height will be measured to be y units.

The below method saves images with different encoder formats of jpeg, png and gif images. You can modify the code for other available formats in C#.

public class ImageUploader
    {

public float Save(Bitmap image, int maxWidth, int maxHeight, int quality, string fileName, string ext)
        {
            // Get the image's original width and height
            int originalWidth = image.Width;
            int originalHeight = image.Height;

            // To preserve the aspect ratio
            float ratioX = (float)maxWidth / (float)originalWidth;
            float ratioY = (float)maxHeight / (float)originalHeight;
            float ratio = Math.Min(ratioX, ratioY);

            float sourceRatio = (float)originalWidth / originalHeight;

            // New width and height based on aspect ratio
            int newWidth = (int)(originalWidth * ratio);
            int newHeight = (int)(originalHeight * ratio);

            // Convert other formats (including CMYK) to RGB.
            Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);

            // Draws the image in the specified size with quality mode set to HighQuality
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.DrawImage(image, 0, 0, newWidth, newHeight);
            }

            ImageCodecInfo imageCodecInfo = null;
            // Get an ImageCodecInfo object that represents the JPEG codec.
            if (ext == ".jpg" || ext == ".jpeg")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Jpeg);
            }
            else if (ext == ".png")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Png);
            }
            else if (ext == ".gif")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Gif);
            }

            // Create an Encoder object for the Quality parameter.
            Encoder encoder = Encoder.Quality;

            // Create an EncoderParameters object. 
            EncoderParameters encoderParameters = new EncoderParameters(1);

            // Save the image as a JPEG file with quality level.
            EncoderParameter encoderParameter = new EncoderParameter(encoder, quality);
            encoderParameters.Param[0] = encoderParameter;
            newImage.Save(uploadsdir + fileName, imageCodecInfo, encoderParameters);

            return sourceRatio;
        }
}
private ImageCodecInfo GetEncoderInfo(ImageFormat format)
        {
            return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid);
        }

Call the code above with the following parameters as below, keeping the following points in mind:

  • SaveImages method below is created keeping in mind, it is written for a WebAPI and the image may be received in the byte array format.
  • Use a very large height value, so the new image is re-sized restricted to new width size for thumb, medium and large sizes based on the aspect ratio.
  • The Quality category specifies the level of compression for an image. When used to construct an EncoderParameter, the range of useful values for the quality category is from 0 to 100. The lower the number specified, the higher the compression and therefore the lower the quality of the image. Zero would give you the lowest quality image and 100 the highest.
public string SaveImages(byte[] imgArr, string filename, string extension, string uploadtype, out float ratio)
        {
            const int THUMB_WIDTH = 120;
            const int MEDIUM_WIDTH = 400;
            const int LARGE_WIDTH = 900;
            const int IMG_HEIGHT = 100000;
            const int IMG_QUALITY = 100;
            ratio = 0.0f;
            string[] extensionwhitelist = new string[] { ".jpg", ".jpeg", ".gif", ".png" };

            ImageUploader uploader = new ImageUploader(uploadtype);
            
            var encfilename = encryptfilename(filename);
            try
            {
                if (!extensionwhitelist.Contains(extension))
                {
                    throw new Exception("Invalid File format.");
                }
                
                TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
                Bitmap bitmapImg = (Bitmap)tc.ConvertFrom(imgArr);

                uploader.SaveOriginal(bitmapImg, IMG_QUALITY, encfilename + extension, extension);
                uploader.Save(bitmapImg, THUMB_WIDTH, IMG_HEIGHT, IMG_QUALITY, "thumb_" + encfilename + extension, extension);
                uploader.Save(bitmapImg, MEDIUM_WIDTH, IMG_HEIGHT, IMG_QUALITY, "medium_" + encfilename + extension, extension);
                ratio = uploader.Save(bitmapImg, LARGE_WIDTH, IMG_HEIGHT, IMG_QUALITY, "large_" + encfilename + extension, extension);
            }
            catch(Exception ex)
            {
                throw new BusinessServiceException("SaveImages", "Failed saving images.", ex);
            }

            return encfilename;
        }

The method encryptfilename can be written using a method of choice for encrypting the filename of the image.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.