Click here to Skip to main content
Click here to Skip to main content

Simple Image Editor with Crop and Resize while Maintaining Aspect Ratio

By , 30 Dec 2008
 
CropResizeSrc

Introduction

I was developing a project that required adding images to a database. Most of the images were acquired from an 8 megapixel digital camera, so the sizes were quite large.  I originally just re-sized the images proportionally to 1024 x 768 and called it good.  But it bothered me that some images contained busy backgrounds or distractions that could be cropped out. This project is the result of my efforts. 

Background 

Note that I don't claim to have written most of the code for this project. I have stood on the shoulders of giants, and learned and reused code from many different CodeProject articles.  Hopefully, the whole is greater than the sum of its parts. This article is based upon code from ImageResizer.aspx and various CodeProject articles.

Using the Code 

The source code should be fairly self explanatory.

The secret is keeping all of the aspect ratios correct.

private static Image CropImage(Image img, Rectangle cropArea)
{
    try {
	Bitmap bmpImage = new Bitmap(img);
	Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
	return (Image)(bmpCrop);
    }
    catch (Exception ex)
    {
	MessageBox.Show(ex.Message, "CropImage()");
    }
    return null;
}

private void saveJpeg(string path, Bitmap img, long quality)
{
    // Encoder parameter for image quality
    EncoderParameter qualityParam = new EncoderParameter(
    System.Drawing.Imaging.Encoder.Quality, (long)quality);

    // Jpeg image codec
    ImageCodecInfo jpegCodec = getEncoderInfo("image/jpeg");

    if (jpegCodec == null)
    {
	MessageBox.Show("Can't find JPEG encoder?", "saveJpeg()");
	return;
    }
    EncoderParameters encoderParams = new EncoderParameters(1);
    encoderParams.Param[0] = qualityParam;
  
    img.Save(path, jpegCodec, encoderParams);
}

private ImageCodecInfo getEncoderInfo(string mimeType)
{
    // Get image codecs for all image formats
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

    // Find the correct image codec
    for (int i = 0; i < codecs.Length; i++)
	if (codecs[i].MimeType == mimeType)
   	   return codecs[i];

    return null;
}

private void btnOK_Click(object sender, EventArgs e)
{
    // output image size is based upon the visible crop rectangle and scaled to 
    // the ratio of actual image size to displayed image size
    Bitmap bmp = null;

    Rectangle ScaledCropRect = new Rectangle();
    ScaledCropRect.X         = (int)(CropRect.X / ZoomedRatio);
    ScaledCropRect.Y         = (int)(CropRect.Y / ZoomedRatio);
    ScaledCropRect.Width     = (int)((double)(CropRect.Width) / ZoomedRatio);
    ScaledCropRect.Height    = (int)((double)(CropRect.Height) / ZoomedRatio);

    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
    {
	try
	{
       bmp = (Bitmap)CropImage(pictureBox1.Image, ScaledCropRect);
	   // 85% quality
	   saveJpeg(saveFileDialog1.FileName, bmp, 85);
	}
	catch(Exception ex)
	{
	   MessageBox.Show(ex.Message, "btnOK_Click()");
	}
    }

    if(bmp != null)
         bmp.Dispose();
}

Points of Interest 

There is a transparent crop box that may be dragged by its corners, or moved by left clicking and moving. The aspect ratio of the crop box is determined by the value in the combo box.   The other combo box simply sets the width of the crop box, and the height is determined by the chosen aspect ratio.  The crop box will snap to a proportional aspect ratio when re-sized.

There are some simple image processing features available; rotate, invert color, gray scale, contrast and brightness. 

NOTE: All of my images are landscape, so I have not spent any time on portrait mode resizing conditions in the code.

History

  • 28th December, 2008: Initial release
  • 30th December, 2008: Updated with corrected code

License

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

About the Author

Member 3647417
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralChange of contrast doesn't workmemberRenniePet16 Apr '13 - 14:27 
The project includes code and controls to change brightness and contrast. Changing brightness works OK, but changing contrast does strange things. I don't think it's possible to change an image's contrast via the ColorMatrix.
QuestionHow to resize ImagememberMember 793228411 Oct '12 - 20:26 
Dear Sirs,
I tested this application.
It is very convenience for me, that Clipping, Rotation, Invert color and B/W change function.
 
But resizing could not done.
Resizing means only Display image? Can I save resized Image?
 
One more question.
I loaded 1400x1400 pixel image, and rotate it, and set clipping area 1400x1400.
And then click OK button, the application alert me "not enough Memory".
My System is Intel i3Core 4MB memory Windows7 Home edition 64bit.
 
Please let me know how to fix them.
Best Regards,
Bigstone
GeneralMy vote of 5memberThe nk6 Oct '11 - 21:07 
Nice article... Smile | :)
GeneralMy vote of 5memberasaab20 Oct '10 - 4:06 
simple, clear, esy to change and integrate into a bigger project. and most importantly, it does the job!!
Perfect !!
Generalset background colormemberBabita Shivade15 Apr '09 - 1:52 
hi,
how we can set background color of the remaining portion which is not cropped by this code.
Questionhow we can crop small imagememberBabita Shivade14 Apr '09 - 19:39 
hi,
this is nice code..but there is some problem in this code when we crop some small size image it is not save properly.for small size image zoomed ratio is very high ,so there is some problem occur ,can anyone provide me best solution for that. its very urgent.
thanks in advance...
GeneralFIND ERROR AND SOLUTIONmember~Dim~8 Apr '09 - 0:45 
YOU FOGOT THIS! =)
        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            if (ImageAspectRatio == 0)
                return;
 

            if (imageWidth > imageHeight)
            {
                this.Height = (int)(((double)this.Width / (double)ImageAspectRatio)) + HeightOffset;
            }
            else
            {             
                this.Height = 800;
            }

GeneralRe: FIND ERROR AND SOLUTIONmemberStephan.Zeller23 Jun '09 - 22:27 
Still there are some errors ... Fixed in VB: Wink | ;)
 
Private Sub Form1_ResizeEnd(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.ResizeEnd
If ImageAspectRatio = 0 Then
Exit Sub
End If
 
If imageWidth > imageHeight Then
ImageAspectRatio = CDbl(imageWidth) / CDbl(imageHeight)
Me.Height = CInt(((Me.Width / ImageAspectRatio))) + HeightOffset
Else
ImageAspectRatio = CDbl(imageHeight) / CDbl(imageWidth)
Me.Height = 800 + HeightOffset
End If
 

UpdateAspectRatio()
 
Me.Refresh()
End Sub
Generalno mercymemberkreont12 Jan '09 - 6:44 
on open large image 40000 x 400
yout application return this error
 

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
 
************** Exception Text **************
System.ArgumentException: Parameter is not valid.
at System.Drawing.Graphics.CheckErrorStatus(Int32 status)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
 

************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
ImageCropResize
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/DOCUME~1/kreso/LOCALS~1/Temp/Rar$EX00.219/ImageCropResize.exe
----------------------------------------
System.Windows.Forms
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
 
************** JIT Debugging **************
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.
 
For example:
 



 
When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.
 
qwqwq

GeneralNote!memberMember 364741729 Dec '08 - 6:36 
Sorry guys! (and gals) Shucks | :->
In my haste to leave for the Holidays, I realized that I uploaded the wrong version of the project. The version currently on the page is broken when saving the cropped image. (scales incorrectly in most cases) I'm away from my development machine until after the new year. I'll get the corrected version posted when I return.

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 30 Dec 2008
Article Copyright 2008 by Member 3647417
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid