Monday, January 21, 2008

How To: SlideShowPro administration in ASP.NET: Image Resizing

For anyone looking to create a simple, yet elegant media gallery, SlideShowPro is hard to beat. It's a great bang for the buck and is fairly simple to integrate into an existing website as it reads data directly from a simple xml file.

This is the first part in a series of posts detailing how to create ASP.Net pages for managing a SlideShowPro gallery. Any gallery "control panel" needs the ability to upload and resize media, so this is where we'll start.

I'm going to show you a simple method of resizing an image in C#. These basic concepts are what I used in building the more advanced, but reusable Imaging class. I've decided not to include the detailed steps in creating the class in this article because it's just too much code and is much easier to follow by looking at the project in Visual Studio.

I know some of you are not interested in the code, so go ahead and just download the assembly and sample pages here:.
Source, compiled assembly, and sample pages

Let's start by importing a few classes:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
You'll be able to paste this code into a page and start using it right away.
private void resize()
    {
        //Open the image to resize
        System.Drawing.Image workingFile = System.Drawing.Image.FromFile("C:\\image-to-resize.tmp");

        //Set some maximum dimensions
        double maxHeight = 400;
        double maxWidth = 400;

        //Determine whether this image is portrait or landscape
        double widthRatio; double heightRatio; double multiplier;

        heightRatio = maxHeight / workingFile.Height;
        widthRatio = maxWidth / workingFile.Width;

        if (widthRatio < heightRatio) // portrait
            multiplier = widthRatio;
        else //landscape
            multiplier = heightRatio;

        // Calculate the proportionate size of the scaled image
        int width = (int)Math.Ceiling(workingFile.Width * multiplier);
        int height = (int)Math.Ceiling(workingFile.Height * multiplier);

        //Create an empty bitmap and graphics object using our new dimensions
        Bitmap workingBitmap = new Bitmap(width, height, workingFile.PixelFormat);
        Graphics workingGraphics = Graphics.FromImage(workingBitmap);
        workingGraphics.Clear(System.Drawing.Color.Gray);

        //Set some quality parameters
        workingGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        workingGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

        //Now draw the image onto our new graphics surface
        workingGraphics.DrawImage(workingFile, 0, 0, workingBitmap.Width, workingBitmap.Height);

        //Save the scaled image to a new location
        workingBitmap.Save("C:\\resized-image.jpg", imageCodec(), imageEncoder(90));

        //Dispose of our graphics objects so no memory is wasted
        workingFile.Dispose();
        workingGraphics.Dispose();
        workingBitmap.Dispose();
    }

    //You'll need these 2 private methods in order to encode the jpg with a respectable quality level
    private EncoderParameters imageEncoder(long quality)
    {
        EncoderParameters encoderParams = new EncoderParameters(1);
        EncoderParameter qualParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
        encoderParams.Param[0] = qualParam;
        return encoderParams;
    }

    private ImageCodecInfo imageCodec()
    {
        ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
        ImageCodecInfo codec = null;
        for (int x = 0; x < encoders.Length; x++)
        {
            if (encoders[x].FormatDescription.ToUpper() == "JPEG")
            {
                codec = encoders[x];
                break;
            }
        }
        return codec;
    }
Here's a simple usage example for those downloading the source:
//Add a reference to the assembly and add a using statement:
using BlueEnum.Utility;

//Create an instance of our imaging component.
Imaging canvas = new Imaging();
//Let's open the temp file in order to resize it.
canvas.Open("C:\\source.jpg");
//Now lets resize to more web friendly dimensions.
canvas.Scale(400, 350); //These are maximums. Resizing will be proportional.

//**Optional Watermark**
string watermarkLocation = "C:\\watermark.png";
canvas.Watermark(watermarkLocation, Imaging.WaterMarkPosition.LowerRight, 5);

//**Optional Remove Source File**
canvas.RemoveSourceOnSave = true;

//We're now ready to save the resized file
canvas.Save("C:\\destination.jpg", 90); //The second parameter is jpg compression.
//Let's dump any resources used by the Imaging class
canvas.Dispose();
canvas = null;
Source, compiled assembly, and sample pages

No comments: