C# – Resizing Image Quality Reduction


I have written a simple PhotoEditor helper class to downscale and crop images uploaded to my website. Everything is working but I am seeing unsatisfactory quality when the image is saved to file. I have read up on the different settings you can tweak below is my setup for resizing, cropping is identical.

    public Image ResizeImage(Image imgToResize, Size size)
        int sourceWidth = imgToResize.Width;
        int sourceHeight = imgToResize.Height;

        float nPercentW = (size.Width/(float) sourceWidth);
        float nPercentH = (size.Height/(float) sourceHeight);

        float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;

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

        var src = imgToResize;

        using (var dst = new Bitmap(destWidth, destHeight, imgToResize.PixelFormat))
            dst.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);

            using (var g = Graphics.FromImage(dst))
                var mime = GetMimeType(imgToResize);
                ImageFormat format;
                if (mime == "image/gif" || mime == "image/png")
                    //convert all gif to png, better resize quality
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(src, 0, 0, dst.Width, dst.Height);
                    format = ImageFormat.Png;
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    format = ImageFormat.Jpeg;
                g.DrawImage(src, 0, 0, dst.Width, dst.Height);

                // At this point the new bitmap has no MimeType
                // Need to output to memory stream
                var m = new MemoryStream();
                dst.Save(m, format);

                var img = Image.FromStream(m);

                return img;

As you can see I am using the suggested settings for Interpolation, Smoothing etc. I am also saving the jpeg with quality 100.

The resultant image has noticeable blurring and artefacts even when resizing down to a modest 75% of its original size. I looked around and this is the recommended way. I found a simplistic way to resize and decided to give that a go.

Bitmap NewImg = new Bitmap(original, new Size(387,257));
editor.SaveImage(@"C:\simpleResize.jpg", NewImg, ImageFormat.Jpeg);

Surprisingly this produces a much nicer image although it is quite a bit bigger ~30% larger in memory footprint.

My question is, what's the difference and what setting am I missing on my resize routine that could account for the uglier result. Id like to get my resize routine to produce the exact same result as the simple resize.

Your help is much appreciated. This is my first foray into image processing.


Simple Resize (82KB)

simple http://img189.imageshack.us/img189/2137/simpleresize.jpg

My Resize (55KB)

complex http://img12.imageshack.us/img12/4023/complexresize.jpg

Best Solution

I found this example snippet of code (sorry I've forgotten the source) that might help you:

// Create parameters
EncoderParameters params = new EncoderParameters (1);

// Set quality (100)
params.Param[0] = new EncoderParameter(Encoder.Quality, 100);

// Create encoder info
ImageCodecInfo codec = null;
foreach (ImageCodecInfo codectemp in ImageCodecInfo.GetImageDecoders())
    if (codectemp.MimeType == "image/jpeg")
        codec = codectemp;

// Check
if (codec == null)
    throw new Exception("Codec not found for image/jpeg");

// Save
image.Save(filename, codec, params);
Related Question