Click here to Skip to main content
15,868,164 members
Articles / Multimedia / GDI+
Article

An Easy to Use Image Resizing and Cropping Control

Rate me:
Please Sign up or sign in to vote.
4.68/5 (14 votes)
31 Oct 2008CPOL2 min read 85K   6.6K   86   18
Allows users to load, resize, and crop an image in "real time" with the bloat and complexity of other programs

The Problem

You need to allow users of your desktop app (WinForms) to resize and/or crop large pictures from within your software, perhaps to allow them to upload professional headshots that need to be of a uniform size or type. Installing and/or instructing the user base on using third party software is not an option.

The Solution

Normally, I would never dream of creating yet another image editing program. However, I found myself in a position where, given the user base, it made sense to create a control that would quickly and easily let users crop out a head shot of a person taken with the average digital camera. The driving force behind this solution was to prevent people from uploading pictures that were too large, both in dimension and file size.

Image 1

Features

  • Easy to use interface.
  • Image resizing done in "real time"; no guessing based on percentages.
  • Required image dimensions can be set at design or runtime. Ensures users will load images of the proper size.
  • Supports loading of and saving to BMP, JPG, GIF, PNG, and TIF files.
  • Initially resizes image to fit in workspace.

Image 2

Image 3

Using the Control

The control can be used out of the box by simply dropping it onto a form and docking it. To integrate it into your solution, simply add it to your form, subscribe to the WorkComplete event, and call GetEditedImage.

C#
imageResizer1.WorkComplete += 
   new ImageResizer.WorkCompleteDelegate(imageResizer1_WorkComplete);

void imageResizer1_WorkComplete(object sender, bool complete)
{
    if (complete)
    {
        pictureBox1.Image = imageResizer1.GetEditedImage();
        // your processing here...
    }
    else // user cancelled
    {
        pictureBox1.Image = null;
    }

    imageResizer1.Reset();
    imageResizer1.Visible = false;
    pictureBox1.Visible = true;
}

Points of Interest

Normally, it is a pain to do custom drawing inside the Paint event of a form. However I "cheated" by using a GroupBox to track the dimensions of the workspace. The GroupBox is anchored so as the control is resized, my coordinates are tracked automatically, and I don't have to worry about drawing outside the boundary. Here is the Paint method for those that are interested:

C#
private void ImageResizer_Paint(object sender, PaintEventArgs e)
{
    // Draws alternating shaded rectangles so user
    // can differentiate canvas from image.
    bool xGrayBox = true;
    int backgroundX = 0;
    while (backgroundX < grpImage.Width)
    {
        int backgroundY = 0;
        bool yGrayBox = xGrayBox;
        while (backgroundY < grpImage.Height)
        {
            int recWidth = (int)((backgroundX + 50 > grpImage.Width) ?
            grpImage.Width - backgroundX : 50);

            int recHeight = (int)((backgroundY + 50 > grpImage.Height) ?
            grpImage.Height - backgroundY : 50);

            e.Graphics.FillRectangle(((Brush)(yGrayBox ?
            Brushes.LightGray : Brushes.Gainsboro)),
            backgroundX, backgroundY, recWidth + 2, recHeight + 2);

            backgroundY += 50;
            yGrayBox = !yGrayBox;
        }
        backgroundX += 50;
        xGrayBox = !xGrayBox;
    }

    if (!SuspendRefresh && DrawnImage != null)
    {
        // if the image is too large, draw only visible portion
        // as dictated by the scrollbars, otherwise draw the whole image.
        if (DrawnImage.Width > grpImage.Width || 
            DrawnImage.Height > grpImage.Height)
        {
            int rectX = 0;
            if (hsbImage.Value > 0)
            {
                rectX = hsbImage.Value;
            }
            int rectY = 0;
            if (vsbImage.Value > 0)
            {
                rectY = vsbImage.Value;
            }
            e.Graphics.DrawImage(DrawnImage, 0, 0,
            new Rectangle( rectX, rectY, grpImage.Width, grpImage.Height),
            GraphicsUnit.Pixel);
        }
        else
        {
            e.Graphics.DrawImage(DrawnImage, 0, 0);
        }

        // Draw the crop rectangle with both yellow and black 
        // so it is easily visible no matter the image.
        if (chkCrop.Checked)
        {
            e.Graphics.DrawRectangle(Pens.Yellow, CropBoxX, 
            CropBoxY, (float)nudCropWidth.Value, (float)nudCropHeight.Value);

            e.Graphics.DrawRectangle(Pens.Black, CropBoxX - 1, CropBoxY - 1,
            (float)nudCropWidth.Value + 2, (float)nudCropHeight.Value + 2);
        }
    }
}

History

  • 29th October, 2008: Initial post
  • 31st October, 2008: Download files updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United States United States
Expert in C#, .NET, WinUI/WPF, Azure, and SQL Server.
I started working with .NET and C# professionally in 2003 and never looked back. I have been an integral part of a dozen complete software lifecycles, been a driving force behind two successful startups, and have led development teams.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Azrul Maulana Ihsan9-Apr-23 6:38
Azrul Maulana Ihsan9-Apr-23 6:38 
QuestionMy vote is 5 nice sample but imageResizer control miising in my Toolbox Pin
Balaram22419-Feb-16 18:32
professionalBalaram22419-Feb-16 18:32 
GeneralMy vote of 5 Pin
Britteandy27-Aug-13 23:48
Britteandy27-Aug-13 23:48 
Generalresize cropbox with mouse event Pin
Babita Shivade15-Apr-09 20:35
Babita Shivade15-Apr-09 20:35 
GeneralSet back ground color in non cropped area of image. Pin
Babita Shivade15-Apr-09 1:55
Babita Shivade15-Apr-09 1:55 
Generalwant to add circle in place of rectangle at the time of cropping. Pin
Babita Shivade13-Apr-09 22:34
Babita Shivade13-Apr-09 22:34 
GeneralRe: want to add circle in place of rectangle at the time of cropping. Pin
Josh Fischer14-Apr-09 4:56
Josh Fischer14-Apr-09 4:56 
GeneralSome nice ideas but implementation is wanting Pin
dhaag4-Jan-09 21:03
dhaag4-Jan-09 21:03 
GeneralHopefully it's a typo ;-) Pin
gholbrook5-Nov-08 6:39
gholbrook5-Nov-08 6:39 
GeneralRe: Hopefully it's a typo ;-) Pin
Josh Fischer5-Nov-08 7:22
Josh Fischer5-Nov-08 7:22 
GeneralThats a nice UI Pin
defwebserver3-Nov-08 17:35
defwebserver3-Nov-08 17:35 
GeneralNice work! Pin
tptshepo30-Oct-08 1:49
tptshepo30-Oct-08 1:49 
GeneralRe: Nice work! Pin
Stumproot4-Nov-08 3:54
Stumproot4-Nov-08 3:54 
GeneralRe: Nice work! Pin
Josh Fischer4-Nov-08 5:55
Josh Fischer4-Nov-08 5:55 
GeneralRe: Nice work! Pin
thirstyDev20-Nov-08 18:12
thirstyDev20-Nov-08 18:12 
GeneralRe: Nice work! Pin
Josh Fischer21-Nov-08 6:53
Josh Fischer21-Nov-08 6:53 
GeneralRe: Nice work! Pin
h3ph3st0s24-Apr-16 11:26
h3ph3st0s24-Apr-16 11:26 
Many thanks for sharing your experience. Thumbs Up | :thumbsup:

Mr. John, is it possible to elaborate more on the code?
I was looking 3 weeks now in internet for information regarding manipulation of GDI from C# and (a) there is a tone of noise that when you look how to crop/move and generally edit an image, by no means you can think of a groupbox(!!!).
So how did you end up using a group box?
What are the benefits with regard to the picturebox, which is a big pain and everybody tries to make tutorial around it.
What are the maths that so fine the distortion of image?
What is your high-level concept around DrawnImage and BaseImage ? How is this relationship built ?
I noticed that nomatter scale of the image, or EVEN i moved the image on the groupbox, the final crop result is as-expected. How can this happen ?

I am sorry for my many questions, but I find that you have deep understanding of the GDI and it seems that 3 weeks of me reading tutorials or craving with sparse codes was a total failure.

Conclusion, good work and thanks.

modified 24-Apr-16 17:50pm.

GeneralUpload Application Pin
Harshdeep Mehta (4700787)29-Oct-08 10:41
Harshdeep Mehta (4700787)29-Oct-08 10:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.