C# Bitmap Image Scaling for Bmp, Jpg, and Png

How do you scale your bmp, jpg, or png images in C#? Use System.Drawing.BitMap and follow the instructions in this article.

(Be sure to wrap all of your MemoryStreams and Bitmap objects with Using statements, so they get disposed, otherwise you’ll have some memory leaks and locks on files.)

First, add references to System.Drawing in your C# Visual Studio project, and you’ll want a using statement near the top of your code too:

using System.Drawing;

Then, we’ll load up our image in to a Bitmap object and save it to a memory stream like this:

string sourceFile = "c:\my.png";

using (Bitmap srcBitmap = new Bitmap(sourceFile))
using (MemoryStream streamSrc = new MemoryStream())
{
srcBitmap.Save(streamSrc, System.Drawing.Imaging.ImageFormat.Jpeg);
We will calculate the area of the source image using the height and width attributes:
	int sourceImageArea = srcBitmap.Width * srcBitmap.Height;

If the source image area exceeds a threshold, we’ll calculate a scale factor that we need to reduce the height and width by. That new scale factor will be applied to get a new width and height.

		float scaleRatio = maxOutputPixelArea;
scaleRatio /= sourceImageArea; // scaleRatio is less than 1
float newW = srcBitmap.Width;
newW *= scaleRatio;
float newH = srcBitmap.Height;
newH *= scaleRatio;

Lastly, we’ll create a new Bitmap to save the converted image to with our new dimensions:

		using (Bitmap resizedImg = ResizeImage(srcBitmap, Convert.ToInt32(newW), Convert.ToInt32(newH)))
using (MemoryStream resizedImgStrm = new MemoryStream())
{
resizedImg.Save(resizedImgStrm, System.Drawing.Imaging.ImageFormat.Jpeg);
imageBytes = resizedImgStrm.ToArray();
// Save imageBytes to file, store to Database, or whatever
}

The full code looks like this:

string sourceFile = "c:\my.png";
int maxOutputPixelArea = 3000000;
using (Bitmap srcBitmap = new Bitmap(sourceFile))
using (MemoryStream streamSrc = new MemoryStream())
{
// Convert the image to byte[]
srcBitmap.Save(streamSrc, System.Drawing.Imaging.ImageFormat.Jpeg);
int sourceImageArea = srcBitmap.Width * srcBitmap.Height;
if (sourceImageArea > maxOutputPixelArea)
{
float scaleRatio = maxOutputPixelArea;
scaleRatio /= sourceImageArea; // scaleRatio is less than 1
float newW = srcBitmap.Width;
newW *= scaleRatio;
float newH = srcBitmap.Height;
newH *= scaleRatio;
using (Bitmap resizedImg = ResizeImage(srcBitmap, Convert.ToInt32(newW), Convert.ToInt32(newH)))
using (MemoryStream resizedImgStrm = new MemoryStream())
{
resizedImg.Save(resizedImgStrm, System.Drawing.Imaging.ImageFormat.Jpeg);
imageBytes = resizedImgStrm.ToArray();
// Save imageBytes to file, store to Database, or whatever
}
}

Finally, the ResizeImage code is this:

private static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}