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.
![](ImageResizer/0start.jpg)
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.
![](ImageResizer/1postload.jpg)
![](ImageResizer/3postadjust.jpg)
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
.
imageResizer1.WorkComplete +=
new ImageResizer.WorkCompleteDelegate(imageResizer1_WorkComplete);
void imageResizer1_WorkComplete(object sender, bool complete)
{
if (complete)
{
pictureBox1.Image = imageResizer1.GetEditedImage();
}
else
{
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:
private void ImageResizer_Paint(object sender, PaintEventArgs e)
{
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 (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);
}
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