.NET Image Scaling in CSharp

94Tr One feature of .NET that I use regularly is image scaling.  I typically use this on web sites that need image upload capabilities.  I assume the user is going to send me an image that is significantly bigger than what I could use and then scale it down before storing it.

I also use this feature so that I only have to store one image.  If I need it at a different size, I can scale it prior to sending it down to the browser.  In this case, I implement .NET page caching so that I don’t have to run the scaling code every time the image is requested.

Image scaling really isn’t that hard.  Here’s how it’s done.

Supporting Stuff

I do image scaling so much that I created a class for it.  It has a supporting property called OriginalImage that is of type System.Drawing.Image that accepts the original image object.  It is supported by a member variable named m_Image that you will see in the rest of my code.

It also has a supporting method named GetEncoderInfo() that returns image Encoder information based on the MIME type that is passed in to it.  Here’s that code:

public System.Drawing.Imaging.ImageCodecInfo
    GetEncoderInfo(String mimeType)
    int i;
    ImageCodecInfo[] encoders;
    encoders = ImageCodecInfo.GetImageEncoders();
    for (i = 0; i < encoders.Length; ++i)
        if (encoders[i].MimeType == mimeType)
            return encoders[i];
    return null;

The main method that does the scaling has the following signature

public byte[] GenerateThumbNail(
    int Width, int Height)

Notice that I’m returning a byte array.  This is because the information is either going to be streamed back to the web browser or stored into a field in the database.  I find storing images in the database much easier to manage than storing them on the file system since I don’t have to keep track of file names.  It’s a personal preference thing.  You could use the byte array to store to the file system if you wanted.


The width and height parameters take the rectangle I want the image to fit into.  I’ve also written my code so that if the parameter is zero, it is ignored.  That is, if we pass in a width of zero and a height of 20, the image is scaled so that it is always 20 pixels wide and the height will be scaled so the image maintains the same aspect ratio.

Here’s the code that determines the scaling ratio

int OriginalWidth = m_Image.Width;
int OriginalHeight = m_Image.Height;
double scale=0.0;

// Scale the image.
// if maxHeight = 0, scale to maxWidth
if (Height == 0)
    scale = (double)Width / (double)m_Image.Width;
    // if maxWidth = 0, scale to maxHeight
else if (Width == 0)
    scale = (double)Height / (double)m_Image.Height;
    // if maxHeight >= maxWidth /w (scale by maxWidth)
else if (((double)Height) >= m_Image.Height *
    ((double)Width) / ((double)m_Image.Width))
    scale = (double)Width / (double)m_Image.Width;
    // if maxWidth > maxHeight/h (scale by maxHeight)
    scale = (double)Height / (double)m_Image.Height;

Height = Convert.ToInt32(m_Image.Height * scale);
Width = Convert.ToInt32(m_Image.Width * scale);

That was probably the hardest part of the code to write.  Getting the math right is what makes scaling difficult–the rest is just API calls.

Next we create a Bitmap object and turn that into a Graphic object.  The properties I set after creating the Graphic object are the property settings that I’ve found produce the best final image.

The last line of code draws the original image into the Graphic object scaled to the new size.

Graphics graphic = Graphics.FromImage(returnBitmap);
graphic.CompositingMode =
graphic.CompositingQuality =
graphic.SmoothingMode =
graphic.InterpolationMode =
graphic.PixelOffsetMode =

graphic.DrawImage(m_Image, new Rectangle(0, 0, Width, Height));

Convert To Image Type and Return

This final bit of code turns the image into a jpg file, stores the image into a memory stream and then converts the memory stream to the byte array that the method returns.  I compress at 99 because that’s what consistently gives me the best image in the end.

EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
System.Drawing.Imaging.Encoder myEncoder;
long Compression = 99L;

myEncoder =
myEncoderParameters =
    new EncoderParameters(1);
myEncoderParameter =
    new EncoderParameter(myEncoder, Compression);
myEncoderParameters.Param[0] =

System.IO.MemoryStream ms =
    new System.IO.MemoryStream();

byte[] returnArray = ms.GetBuffer();

return returnArray;

Related Post

2 Responses to “.NET Image Scaling in CSharp”

Leave a Reply

Comment Policy:

  • You must verify your comment by responding to the automated email that is sent to your email address. Unverified comments will never show.Leave a good comment that adds to the conversation and I'll leave your link in.
  • Leave me pure spam and I'll delete it.
  • Leave a general comment and I'll remove the link but keep the comment.

Notify me of followup comments via e-mail