Page 1 of 1

Working with the System.Drawing Namespace Part I

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1642
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Posted 17 August 2008 - 10:02 PM

In this Four Part Tutorial Section on working with images using the System.Drawing Namespace so for Part I we will be looking at scaling an image to fit the dimensions of a PictureBox Control.

Recently I have seen several questions regarding using Scrollbar's in a PictureBox. While this can be done, and is done quite often, I personally prefer to scale the image down to fit within the dimensions of the PictureBox that's holding the image. Some will ask how it's possible to accomplish this without distorting the image itself, some will ask how it's even possible to begin with. Given these questions I thought it would be a nice test to see if I could do this without degrading the image too bad, regardless of the image size or the size of the PictureBox.

For the first question, in order to change (or scale) and image liek this without degrading the quality too bad you would want to re-draw the image once it's re-sized, thus clearing the image up. To accomplish this you play around with the InterpolationMode, which is located in the System.Drawing.Drawing2D Namespace. For this example we will be setting it to HighQualityBicubic, which is used to make sure the quality stays put while shrinking the image.

The first thing we will do is to write a method which returns a Size, which will hold the new height and width of our image. This method will require four parameters:
  • Current Height (height of the image)
  • Current Width (width of the image)
  • Destination Height (the height we want)
  • Destination Width (the width we want
The first two we will be getting from our image itself, the final two will come from the dimensions of the PictureBox housing the image. We will ensure proper scaling by doing everything based on a multiplier, and that will be calculated based on whether the image is landscape or portrait style. Here is how we calculate the new dimensions of our image:


public Size GenerateImageDimensions(int currW, int currH, int destW, int destH)
{
    //double to hold the final multiplier to use when scaling the image
    double multiplier = 0;

    //string for holding layout
    string layout;

    //determine if it's Portrait or Landscape
    if (currH > currW) layout = "portrait";
    else layout = "landscape";

    switch (layout.ToLower())
    {
        case "portrait":
            //calculate multiplier on heights
            if (destH > destW)
            {
                multiplier = (double)destW / (double)currW;
            }

            else
            {
                multiplier = (double)destH / (double)currH;
            }
            break;
        case "landscape":
            //calculate multiplier on widths
            if (destH > destW)
            {
                multiplier = (double)destW / (double)currW;
            }

            else
            {
                multiplier = (double)destH / (double)currH;
            }
            break;
    }

    //return the new image dimensions
    return new Size((int)(currW * multiplier), (int)(currH * multiplier));
}




Now we have our new dimensions, so lets apply that to our image, and make sure we adjust the image to retain as much or the original quality as possible


private void SetImage(PictureBox pb)
{
    try
    {
        //create a temp image
        Image img = pb.Image;

        //calculate the size of the image
        Size imgSize = GenerateImageDimensions(img.Width, img.Height, this.pictureBox1.Width, this.pictureBox1.Height);

        //create a new Bitmap with the proper dimensions
        Bitmap finalImg = new Bitmap(img, imgSize.Width, imgSize.Height);

        //create a new Graphics object from the image
        Graphics gfx = Graphics.FromImage(img);

        //clean up the image (take care of any image loss from resizing)
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

        //empty the PictureBox
        pb.Image = null;

        //center the new image
        pb.SizeMode = PictureBoxSizeMode.CenterImage;

        //set the new image
        pb.Image = finalImg;
    }
    catch (System.Exception e)
    {
        MessageBox.Show(e.Message);
    }
}




Believe it or not that's it! We have just proportionately scaled an image to fit within our PictureBox, and maintained as much of the original images quality as possible. To use this we can add it into the Load event of a Forum, or even in the Click event of a button, like so


private void Form1_Load(object sender, EventArgs e)
{
    SetImage(pictureBox1);
}



I hope this small bit of code was useful, and Ill be doing more writing in the future on working with images and GDI with the .Net Framework. Thanks for reading :)

Is This A Good Question/Topic? 0
  • +

Page 1 of 1