Rotate, Flip, and Resize Images in .NET

Often times if you’re writing a web application that deals with user uploaded photographs and other images, a nice feature set to have is one that allows users to do basic manipulations on their photos, such as rotating, flipping, and resizing (the last being very important for download friendly images). Luckily, the .NET framework makes such functionality easy to implement.

Read the Image

Once the image has been uploaded and saved into a directory somewhere accessible by the web server, the first step common to all the procedures is to take the image data inside of the file and get it into memory usable by .NET. We do this by loading the image into a System.Drawing.Bitmap object. One of the constructors of Bitmap class can take the filename of an image, thereby automatically decoding the format and reading in the data into the Bitmap object. .NET supports the most common image formats, such as JPEG, GIF, BMP, and PNG.

        Dim PhotoBMP As Bitmap

        PhotoBMP = New Bitmap(“myfile.jpg”)

Above we have statically specified a filename, but you may, of course, dynamically pass in the filename saved on the webserver.

Flips and Rotations

Reorienting the image is incredibly easy. The Bitmap class contains a method called “RotateFlip” that does what you would think – rotates and/or flips. The RotateFlip method takes a single argument, one of RotateFlipType type. Intellisense will enumerate all the options, but each combination of rotation and flip is included: 90, 180, 270 degrees, and flips across X, Y or both axes.

        PhotoBMP.RotateFlip(RotateFlipType.Rotate270FlipNone)

Above we rotate our image clockwise 270 degrees (i.e. counter-clockwise 90 degrees). We do not perform a flip.

        PhotoBMP.RotateFlip(RotateFlipType.RotateNoneFlipY)

Above we flip our image across the Y axis but do not perform a rotation. You may also combine both flips and rotations simultaneously if desired.

Saving (and Converting) the Image

At this point, our reorientation has only been performed upon the bitmap data we have in memory, our file is still untouched. We can save our changes back to the original file, or to a new file if desired. The Bitmap class contains an easy to use Save method.

        PhotoBMP.Save(“myfile.jpg”)

Save is overloaded in a number of ways, but you may also specify a filetype as the second argument. In our example, if we wanted to convert our jpg to a png:

        PhotoBMP.Save(“myfile.png”,ImageFormat.Png)

Very easy as can be seen, no need to lookup file formats and encodings. You may also want to read in the current extension to direct what actions are taken. I use the following regular expression to parse the ending extension of the file.

        Regex.Match(FileName, ".[^.]+$")

Resizing Images

Resizing images is a little more difficult, but not too bad once you know the procedure. You start by loading bitmap data in the same fashion we did for rotating and flipping. Assuming you want to keep the image in proportion when changing the size, as well as resize with a maximum resolution in mind, we’ll need to calculate the aspect ratio of the image and our conversion coefficient. This may sound complicated, but fear not.

Calculate Aspect Ratio

There are a few methods of doing the math, but in general we know the maximum dimension we want. E.g. 1024×768, 800×600, 640×480, etc. We calculate the aspect ratio of our maximum desired size by dividing the width by the height. In these examples it is 1.333.

Then we must calculate the aspect ratio of the current image. We can obtain the width and height of our bitmap with the width and height properties of the Bitmap class. We know if we have a greater aspect ratio than our target max size’s aspect ratio, then our width is larger and is the confining dimension. If our aspect ratio is less, our height is larger and is the confining dimension. Once we know our confining dimension, to get the conversion coefficient, we divide our current image confining dimension size by the target confining dimension size.

E.g. If we’re converting 2048×1800 to a maximum of 1024×768, we calculate our target image aspect ratio, which we already know is 1.333. Then we calculate our original image aspect ratio, which is 1.138. This is less than 1.333, so we know height is our confining dimension. So we divide 1800 by 768 to get our conversion coefficient, or 2.344. Now we can calculate our target width size by dividing our current width by 2.344, which is 874. Our new image will by 874×768.

Confused? It’s not really as bad as it sounds. First you’re figuring out which dimension will match the largest dimension of your target size, then you’re decreasing the other dimension by the same amount. Here it is in code.

        OrigAspectRatio = PhotoBMP.Width / PhotoBMP.Height

        TargetAspectRatio = 1024 / 768

        If OrigAspectRatio < TargetAspectRatio
   	     ‘Height is confining
	     NewHeight = 768
	     NewWidth = PhotoBMP.Width / (PhotoBMP.Height / 768)
        Else
	     ‘Width is confining
	     NewWidth = 1024
  	     NewHeight = PhotoBMP.Height / (PhotoBMP.Width / 1024)
        End If

Perform the Resize

Now we have our target width and height via good old fashioned math, now the technical bits for .NET to perform its magic. .NET can perform resizing via the Graphics class, by resizing data from the original bitmap data into a new, smaller bitmap. First we make a new, blank Bitmap of the correct new size.

        NewBMP = New Bitmap(newWidth, newHeight)

Then we create a new Graphics image using the reference of this new Bitmap object.

        ConvertGraphics = Graphics.FromImage(NewBMP)

Then we specify the method of scaling the image. Different methods work better for different amounts of scaling, but High Quality Bicubic is the one I tend to use.

        ConvertGraphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

Now comes the actual conversion, we use the DrawImage method to draw our original bitmap into the new bitmap at the new size (at the starting coordinates of 0,0 in the new bitmap

        ConvertGraphics.DrawImage(PhotoBMP, 0, 0, NewBMP.Width, NewBMP.Height)

Dispose our old bitmap

        PhotoBMP.Dispose()

Save our new

        NewBMP.Save(“new.jpg”, ImageFormat.Jpeg)

And dispose

        NewBMP.Dispose()

And we’re done! You can also use the Graphics object to perform a number of paint-oriented operations on your image, such as lines and drawing text, but that you can have fun experimenting with.

With the exception of resizing which requires a few calculations, .NET makes image manipulation exteremly easy, and when combined into a web application, offers users some useful tools at virtually no cost to you.

Leave a Reply

Your email address will not be published.