Resize Images with Crop and Quality Control

There are plenty of snippets out there to resize images, and I went through a lot of them, while trying to implement this.
But a bunch of them gave me quality issues and some others came with other issues of their own.

So here’s the code we used to resize images, with the provision to adjust for quality (depending on how much you are willing to sacrifice for bandwidth!)

        internal static byte[] ResizeAndCropImage(System.Drawing.Image image, int requestedWidth, int requestedHeight, bool crop = true)
        {
            if (image == null) return null;

            int sourceWidth = image.Width;
            int sourceHeight = image.Height;

            if (sourceWidth == 0 || sourceHeight == 0) return null;

            // *************** Figure out resize % ***************

            double percentageResize = 1;

            if (requestedWidth == 0 && requestedHeight == 0)
            {
                percentageResize = 1;
            }
            else if (requestedWidth == 0 && requestedHeight > 0)
            {
                if (sourceHeight <= requestedHeight)
                {
                    percentageResize = 1;
                }
                else
                {
                    percentageResize = (double)requestedHeight / sourceHeight;
                }
            }
            else if (requestedWidth > 0 && requestedHeight == 0)
            {
                if (sourceWidth <= requestedWidth)
                {
                    percentageResize = 1;
                }
                else
                {
                    percentageResize = (double)requestedWidth / sourceWidth;
                }
            }
            else if (requestedWidth <= sourceWidth && requestedHeight <= sourceHeight)
            {
                percentageResize = crop ? Math.Max((double)requestedWidth / sourceWidth, (double)requestedHeight / sourceHeight)
                    : Math.Min((double)requestedWidth / sourceWidth, (double)requestedHeight / sourceHeight);
            }
            else if ((requestedWidth <= sourceWidth && requestedHeight > sourceHeight)
                || (requestedWidth > sourceWidth && requestedHeight <= sourceHeight)
                || (requestedWidth > sourceWidth && requestedHeight > sourceHeight))
            {
                percentageResize = 1;
            }

            int destHeight = (int)Math.Round(sourceHeight * percentageResize);
            int destWidth = (int)Math.Round(sourceWidth * percentageResize);

            using (Bitmap resizedBmp = new Bitmap(destWidth, destHeight))
            {
                // *************** Resize ***************

                using (Graphics graphics = Graphics.FromImage(resizedBmp))
                {
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.DrawImage(image, 0, 0, destWidth, destHeight);
                }

                // *************** Figure out crop px ***************

                int cropX = crop && (destWidth > requestedWidth && requestedWidth > 0) ? (destWidth - requestedWidth) / 2 : 0;
                int cropY = crop && (destHeight > requestedHeight && requestedHeight > 0) ? (destHeight - requestedHeight) / 2 : 0;

                // *************** Crop ***************

                Rectangle rectangle = new Rectangle(cropX, cropY, destWidth - (cropX * 2), destHeight - (cropY * 2));

                using (Bitmap croppedBmp = resizedBmp.Clone(rectangle, resizedBmp.PixelFormat))
                using (MemoryStream ms = new MemoryStream())
                {
                    ImageCodecInfo imgCodec = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == image.RawFormat.Guid);
                    EncoderParameters codecParams = new EncoderParameters(1);

                    codecParams.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
                    croppedBmp.Save(ms, imgCodec, codecParams);
                    return ms.ToArray();
                }
            }
        }

The quality can be controlled by passing in the % in the codec params above. You can see, we have it set to 95% here. You could ofcourse make this configurable and choose to pass in the % with the width and height.

To get the System.Drawing.Image object from a local file:

System.Drawing.Image image = System.Drawing.Image.FromFile("C:\...\myimage.jpg");

If you wanted to resize an image using a url (say for instance in your application you stored user uploaded images in Salesforce (Storing user profile image using Salesforce Connector with Sitecore) and wanted to resize this image to display on your site), then you could use the following to get the System.Drawing.Image object:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imagePath);
                            using (WebResponse response = request.GetResponse())
                            using (HttpWebResponse httpResponse = (HttpWebResponse)response)
                            {
                                if (httpResponse.StatusCode != HttpStatusCode.OK)
                                {
                                    EndAsyncTask();
                                    return;
                                }
                                using (Stream imageStream = response.GetResponseStream())
                                {
                                    if (imageStream == null)
                                    {
                                        EndAsyncTask();
                                        return;
                                    }

                                    image = Image.FromStream(imageStream);
                                }
                            }

Here are some sample outputs!

Original Image (768X768):
P1020131

300X?
Imageresizer
?X100
Imageresizer (1)
300X200
Imageresizer (3)
100X200
Imageresizer (2)
Advertisements

2 thoughts on “Resize Images with Crop and Quality Control

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s