One of the most common methods to improve page load times on your website is to reduce your image sizes.
That can be done by changing the file type often times, such as converting a .png
file to a .webp
file. WebP images are optimized image files specifically designed for the web. But an easier way to improve your performance is to simply resize the images physical dimensions directly on the server.
The following is a C# script that I use daily on all of my websites in order to scale down their image size. It works by leveraging the built-in .NET System.Drawing
classes in order to create a virtual Bitmap with the new dimensions and then saving this new file on the server.
I will show the code first and then do a bit of background and further explanation right after.
C# Code to Resize an Image
private void CreateThumbnail(string filename, string path, int maxWidth, int maxHeight){
try
{
System.Drawing.Image img = System.Drawing.Bitmap.FromFile(Server.MapPath(string.Format("{0}{1}", path, filename)));
string strName = string.Format("thumb_{0}", filename);
System.Drawing.Image newImg;
double newWidth = img.Width;
double newHeight = img.Height;
// finds the small dimensions
for (int i = 99; i > 0; i--)
{
newWidth = (double)(i / 100.0) * newWidth;
newHeight = (double)(i / 100.0) * newHeight;
if (newWidth <= maxWidth && newHeight <= maxHeight)
{
break;
}
}
var bmSmall = new System.Drawing.Bitmap(img, new System.Drawing.Size((int)newWidth, (int)newHeight));
newImg = (System.Drawing.Image)(bmSmall);
newImg.Save(Server.MapPath(string.Format("{0}{1}", path, strName)));
img.Dispose();
newImg.Dispose();
}
catch (Exception ex)
{
}
}
You can copy that function as is as it is written generically to run alongside any other code. But for the full breakdown, read on.
Breaking Down the Function
First up, let's take a look at the functions signature.
private void CreateThumbnail(string filename, string path, int maxWidth, int maxHeight){
The first argument, filename
, is the name of the file on the file system that you wish to resize. This assumes that you already have the file stored somewhere on your server after an upload.
The second argument, path
, is the relative directory path of your file.
~/images/blog/
Combining the directory path with the filename
gives us the full relative path to the image. The 3rd and 4th arguments are the maximum dimensions that we want the new image to encompass.
Note that this particular implementation will ensure that ratio's are maintained during the resize process.
System.Drawing.Image img = System.Drawing.Bitmap.FromFile(Server.MapPath(string.Format("{0}{1}", path, filename)));
Note that I left the full namespace class names in each variable declaration for clarification as to where these classes are located.
The first thing that you'll need to do is to create a Drawing.Image
object instantiated with your uploaded image file's path. You can get the actual server image path using the Server.MapPath
method, which takes in a relative path URL as its argument.
For this implementation, I want to keep both the original full-sized image and the new image on the server, so I will be saving the new file with the "thumb_" prefix on the original filename.
string strName = string.Format("thumb_{0}", filename);
Here are a few more variable declarations to include:
System.Drawing.Image newImg;
double newWidth = img.Width;
double newHeight = img.Hxeight;
The newImg
variable will reference the final Image object after being resized. For now however, it will be uninitialized. The newWidth
and newHeight
variables will be updated to the corresponding resized ratios. But for now, they are initialized to the original dimensions.
How to scale the image
The actual resizing happens with the following for loop, in which the original dimensions are resized on a percentage basis (99%, 98%, 97%, ...) until they reach the maximum width and height passed in through the parameters.
// finds the small dimensions
for (int i = 99; i > 0; i--)
{
newWidth = (double)(i / 100.0) * newWidth;
newHeight = (double)(i / 100.0) * newHeight;
if (newWidth <= maxWidth && newHeight <= maxHeight)
{
break;
}
}
Once the desired size has been found, a break
statement terminates the loop.
We can now create a new Bitmap
object based on the new dimensions and the original Image
object.
var bmSmall = new System.Drawing.Bitmap(img, new System.Drawing.Size((int)newWidth, (int)newHeight));
Notice that the 2nd argument to the Bitmap
constructor is an instance of the Drawing.Size
class, which takes in both the width and height arguments as integers.
The last step is a simple conversion from Bitmap
to Drawing.Image
, so that we can call the Save
method of the Drawing.Image
class.
newImg = (System.Drawing.Image)(bmSmall);
newImg.Save(Server.MapPath(string.Format("{0}{1}", path, strName)));
We'll save the image with the new "thumb_" prefix onto the original file path and lastly dispose of any remaining resources.
img.Dispose();
newImg.Dispose();
Common Issues When Resizing Images in C#
Even though the code is relatively straightforward, there are a few common hiccups you might run into when resizing images using System.Drawing
in C#:
1. Blurry Output
If your resized image comes out noticeably blurry, it’s usually due to the interpolation mode being left at its default. By default, the quality is set to low. You can improve this by creating a Graphics object from your Bitmap and explicitly setting a higher-quality interpolation mode:
using (Graphics g = Graphics.FromImage(bmSmall))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(img, 0, 0, newWidth, newHeight);
}
This extra step ensures the final output maintains better clarity, especially for high-res original files.
2. File Access Exceptions
If you’re working with files on a busy server or multi-threaded environment, make sure the file isn’t being accessed by another process. Locking or incorrect file permissions can throw exceptions or create corrupted output files. A quick try-catch like in the example helps handle this, but it’s always good to log those errors during development.
And that's all there is to an image resize. As mentioned, the code is left generic so that you can implement it into any .NET C# project.
If you found this script useful, let me know and leave a comment
below and feel free to suggest any improvements that could be made.