Search code examples
c#graphicsimaging

Scaling a System.Drawing.Bitmap to a given size while maintaining aspect ratio


I want to scale a System.Drawing.Bitmap to at least less than some fixed width and height. This is to generate thumbnails for an image gallery on a website, so I want to keep the aspect ratio the same.

I have some across quite a few solutions but none seem to really do what I need; they revolve around scaling based on keeping the width or the height the same but not changing both.

An example:

If I have a 4272 by 2848 image and I want to scale it to a size of 1024 by 768, then the resulting image should be 1024 by 683 and padded (with a black border) to 1024 by 768.

How can I do this with images larger than the required size and smaller than the require sized and also pad images which don't come out to the exact size I need once scaled?


Solution

  • Target parameters:

    float width = 1024;
    float height = 768;
    var brush = new SolidBrush(Color.Black);
    

    Your original file:

    var image = new Bitmap(file);
    

    Target sizing (scale factor):

    float scale = Math.Min(width / image.Width, height / image.Height);
    

    The resize including brushing canvas first:

    var bmp = new Bitmap((int)width, (int)height);
    var graph = Graphics.FromImage(bmp);
    
    // uncomment for higher quality output
    //graph.InterpolationMode = InterpolationMode.High;
    //graph.CompositingQuality = CompositingQuality.HighQuality;
    //graph.SmoothingMode = SmoothingMode.AntiAlias;
    
    var scaleWidth = (int)(image.Width * scale);
    var scaleHeight = (int)(image.Height * scale);
    
    graph.FillRectangle(brush, new RectangleF(0, 0, width, height));
    graph.DrawImage(image, ((int)width - scaleWidth)/2, ((int)height - scaleHeight)/2, scaleWidth, scaleHeight);
    

    And don't forget to do a bmp.Save(filename) to save the resulting file.