Make bitmap extension methods that resize bitmaps in C#

[bitmap extension methods]

The post Resize pictures in a directory to specific widths or heights in C# lets you resize all of the pictures in a directory. This example extracts the key method that resizes files and places it in a new Bitmap extension method.

This example actually makes two new extension methods. The first version resizes a bitmap and returns a new bitmap with a given width and height.

The second version resizes the bitmap’s width, height, or both. If you do not want to specify both the width and height, the method calculates the one that you do not specify so it resizes the image without distortion.

Extension Classes

Recall that extension methods must be public static and must be contained inside classes that are also public static. This example places both versions of the Resize bitmap extension methods in the Extensions class. The following code shows the class’s declaration and basic structure.

public static class Extensions
{
    // Return a resized version of the bitmap.
    public static Bitmap Resize(this Bitmap bm,
        int new_width, int new_height)
    {
        ...
    }

    // Resize the image, scaling uniformly if
    // set_width and set_height are not both true.
    public static Bitmap Resize(this Bitmap bm,
        bool set_width, bool set_height, int new_width, int new_height)
    {
        ...
    }
}

You can see that the class and its two bitmap extension methods are declared public static.

The first parameter to each of the extension methods is this Bitmap bm. That means the Bitmap class is the class that these methods extend. For example, if my_picture is a bitmap, then you could use the following code to make a copy of that bitmap that has width 512 and height calculated to resize without distortion.

Bitmap new_bitmap = my_picture.Resize(true, false, 512, 0);

This stes the new image’s width to 512 and its height to the appropriate value to prevent distortion.

The following sections describe the two bitmap extension methods.

Resize Version 1

The following code shows the first version of the Resize bitmap extension methods.

// Return a resized version of the bitmap.
public static Bitmap Resize(this Bitmap bm,
    int new_width, int new_height)
{
    // Make rectangles representing the original and new dimensions.
    Rectangle src_rect = new Rectangle(0, 0, bm.Width, bm.Height);
    Rectangle dest_rect = new Rectangle(0, 0, new_width, new_height);

    // Make the new bitmap.
    Bitmap bm2 = new Bitmap(new_width, new_height);
    using (Graphics gr = Graphics.FromImage(bm2))
    {
        gr.InterpolationMode =
            InterpolationMode.HighQualityBicubic;
        gr.DrawImage(bm, dest_rect, src_rect,
            GraphicsUnit.Pixel);
    }

    return bm2;
}

This method takes as parameters a new desired with and height. It makes rectangles representing the image’s original and desired dimensions.

The code then creates a new bitmap of the desired size and makes an associated Graphics object. It sets that object’s InterpolationMode to smoothly resize the image and uses the DrawImage method to draw the original image onto the new bitmap. The method finished by returning the new bitmap.

Resize Version 2

The previous method returns a bitmap with the desired dimensions even if that distorts the image. The following version calculates the width or height to prevent distortion.

// Resize the image, scaling uniformly if
// set_width and set_height are not both true.
public static Bitmap Resize(this Bitmap bm,
    bool set_width, bool set_height, int new_width, int new_height)
{
    // Calculate the new width and height.
    if (!set_width) new_width = bm.Width * new_height / bm.Height;
    if (!set_height) new_height = bm.Height * new_width / bm.Width;

    // Resize and return the image.
    return bm.Resize(new_width, new_height);
}

If the set_width parameter is false, then the method calculates the new width to match the scale determined by the original and new heights.

Similarly if the set_height parameter is false, the method calculates the new height to match the scale determined by the original and new widths.

If both set_width and set_height are true, the code uses them as they are passed into the method. If both of those parameters are false, then the method may produce unpredictable results depending on the values of new_width and new_height. That should probably be treated as an error and you are welcome to add a test for that situation if you like.

After it has calculated new_width or new_height if necessary, the method calls the precious extension method to resize the bitmap and returns the result.

SaveImage

While I was at it, I also added another method to the bitmap extension methods. This method is described in the post Save images with an appropriate format depending on the file name’s extension in C#. The following code shows the new extension method.

// Save the file with the appropriate format.
public static void SaveImage(this Image image, string filename)
{
    string extension = Path.GetExtension(filename);
    switch (extension.ToLower())
    {
        case ".bmp":
            image.Save(filename, ImageFormat.Bmp);
            break;
        case ".exif":
            image.Save(filename, ImageFormat.Exif);
            break;
        case ".gif":
            image.Save(filename, ImageFormat.Gif);
            break;
        case ".jpg":
        case ".jpeg":
            image.Save(filename, ImageFormat.Jpeg);
            break;
        case ".png":
            image.Save(filename, ImageFormat.Png);
            break;
        case ".tif":
        case ".tiff":
            image.Save(filename, ImageFormat.Tiff);
            break;
        default:
            throw new NotSupportedException(
                "Unknown file extension " + extension);
    }
}

This code uses the Path class’s GetExtension method to get the file’s extension (such as .png or .gif) and converts it to lower case. It then uses a switch statement to save the image in the format that is appropriate for that file extension.

LoadBitmap

This example loads bitmap files in a using block so they are automatically disposed when the program is done with them. In contrast some examples need to keep an image for a prolonged period of time. During that time the program may keep the image’s file locked so you cannot edit or delete it.

One of the tools I use fairly frequently is a method to open a file without keeping its file locked. This example doesn’t really need that feature, but I decided to add it to the Extensions class anyway so I could find it easily later. The following code shows the method.

// Load a bitmap without locking its file.
public static Bitmap LoadBitmap(string filename)
{
    using (Bitmap bm = new Bitmap(filename))
    {
        return new Bitmap(bm);
    }
}

The method loads the bitmap in a using block so it is automatically disposed when the method ends. Inside the block, the code make a new bitmap created by copying the first one. It then returns this new bitmap.

Unfortunately there is no way to add a static extension method to a class, so we can’t make this a method of the Bitmap class. We could make it a non-static Bitmap extension, but it seems silly to make you create an instance of the Bitmap class just to create a new Bitmap. So this method is part of the Extensions class. You can use it as in the following statement.

Bitmap bm = Extensions.LoadBitmap(file_info.FullName);

Conclusion

These bitmap extension methods allow you to easily resize bitmaps, load bitmaps, and save them in appropriate formats. If you do those things as often as I do, you’ll want to add these methods to your programming toolkit.

Download the example program to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in extensions, files, graphics and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

2 Responses to Make bitmap extension methods that resize bitmaps in C#

  1. Richard Moss says:

    Two possible errors: The second “Resize Version 1” header probably wanted to be “2” and the second paragraph of “LoadBitmap” – ” This example does really need that feature” I assume “doesn’t really need” given the wording of the rest of the sentence.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.