In C# it can be tiresome to do certain image editing functions using GDI+. This post has some fun editing methods which can come in handy at times. I have also included a nice little C# program to show all the functionality of the methods below.
Saving a Jpeg
The first thing to do here is set up the method signature with the input parameters. These are the save file path (string), the Image to save (System.Drawing.Bitmap), and a quality setting (long).
private void saveJpeg(string path, Bitamp img, long quality)
The next few things to do are setting up encoder information for saving the file. This includes setting an EncoderParameter for the quality of the Jpeg. The next thing is to get the codec information from your computer for jpegs. I do this by having a function to loop through the available ones on the computer and making sure jpeg is there. The line under that makes sure that the jpeg codec was found on the computer. If not it just returns out of the method.
The last thing to do is save the bitmap using the codec and the encoder infomation.
{
// Encoder parameter for image quality
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, quality);
// Jpeg image codec
ImageCodecInfo jpegCodec = this.getEncoderInfo("image/jpeg");
if(jpegCodec == null)
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;
}
Cropping
The method takes two objects - the image to crop (System.Drawing.Image) and the rectangle to crop out (System.Drawing.Rectangle). The next thing done is to create a Bitmap (System.Drawing.Bitmap) of the image. The only thing left is to crop the image. This is done by cloning the original image but only taking a rectangle of the original.
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea,
bmpImage.PixelFormat);
return (Image)(bmpCrop);
}
Resizing
This next set of code is a slightly longer and more complex. The main reason this code is longer is because this resize function will keep the height and width proportional.
To start with we see that the input parameters are the image to resize (System.Drawing.Image) and the size (System.Drawing.Size). Also in this set of code are a few variables we use. The first two are the source height and width which is used later. And there are 3 other variables to calculate the proportion information.
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
}
The next step is to actually figure out what the size of the resized image should be. The first step is to calculate the percentages of the new size compared to the original. Next we need to decide which percentage is smaller because this is the percent of the original image we will use for both height and width. And now we calculate the number of height and width pixels for the destination image.
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
The final thing to do is create the bitmap (System.Drawing.Bitmap) which we will draw the resized image on using a Graphics (System.Drawing.Graphics) object. I also set the interpolation mode, which is the algorithm used to resize the image. I prefer HighQualityBicubic, which from my testing seems to return the highest quality results. And just to clean up a little I dispose the Graphics object.
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
And this gives us the final code.
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
Here is the source code and a C# VS2005 Express Edition solution with the needed methods and some test code. Click Me for Code
05/04/2007 - 13:52
Like the tutorial! Thanks :)
06/05/2009 - 01:37
I want to process the *.img & *.tif format images by using the C# codings. Any body could you assit me?
05/23/2007 - 08:07
Nice tutorial! But it would be nice to put up how to resize images without preserving the aspect ratio as well. I've been very bugged up over that. D=
05/23/2007 - 12:10
I can answer that right here. To resize the image without preserving the aspect ratio just skip the ratio calculations. Just set
destWidthtosize.WidthanddestHeighttosize.Heightand you're all set.06/11/2007 - 01:34
its really nice to see this example. i'm very thankfull to this code.
06/20/2007 - 05:47
Thanks, thanks, thanks
06/26/2007 - 04:59
Thankx.
finally i found what i looked...
07/01/2007 - 09:59
Thanks
07/02/2007 - 15:51
For resizing you can also use
Image.GetThumbnailImage.07/02/2007 - 19:51
Image.GetThumbnailImagedoes not use interpolation when resizing, so loss of quality can be a concern. For quick resizing where quality is not important,GetThumbnailImageis definitely a good alternative.07/25/2007 - 17:49
Thx for tutorial! I was looking for resizing info other than
GetThumbnailImage.Though when I compared my resized pics with those generated from 'gthumb', the quality of mine isn't good enough (and they take less space), even with a quality level of 100. Gthumb uses essentially the same jpeg encoders I would think, but doesn't use C#/.NET. Any suggestions to get yet higher quality thumbs ?
07/25/2007 - 18:15
I would be interested in seeing your results. When I run the above code at quality 100, I get very nice looking thumbnails. Here's an example I just ran. It was originally a 512x512 that I ran through the
resizeImagefunction, then ran the output through thesaveJpegfuntion.As far as I can tell, there is very little (if any) loss of quality. Here were my steps:
Image i = resizeImage(b, new Size(100, 100));
saveJpeg("C:\\test_resize.jpg", (Bitmap)i, 100);
If you want to post links to your images (you won't be able to put an image tag in the comment) and the code you're using, we can take a look to try to see where the error might be.
07/26/2007 - 03:54
A comparison of the ouput can be found at http://basik.studentenweb.org/pics/
I now use the exact methods (resize and save) presented here and:
Image i = resizeImage(b, new Size(120, 100));
saveJpeg(String.Concat(fileName.Replace(sourceDirectory,
destinationDirectory), ".thumb.jpg"),(Bitmap)i, 100);
I should also mention I am using mono instead of .NET since I'm working on a Linux environment. But i don't think that should matter ?
07/26/2007 - 11:03
I installed Mono (on my Windows machine), compiled, and ran the code and I got the exact same thumbnail that I got using .NET. Mono isn't a 100% implementation of .NET (although they're very close) and I'm guessing you ran across a bug in their Linux version. I did some research and couldn't find any instances of other people experiencing the same issue. If you have a Windows machine available, try running the code on that and if the results are better, post a bug report to Mono. If there is a bug, they may have some known work-arounds.
08/13/2007 - 03:21
Very helpful tutorial. Good luck.
08/20/2007 - 12:48
Thankx.
Finally i found what i'm looking for....
08/20/2007 - 12:51
here the image format is of jpg..
can i use it fot gif..
by replacing
ImageCodecInfo jpegCodec = this.getEncoderInfo("image/gif");i didnt run the code..
08/20/2007 - 17:43
Ram, yes you can. That's the only thing you have to change in order to make it a gif file. Remember that it will use a default color pallet of 256 colors so quality might be an issue depending on your application.
08/21/2007 - 00:05
Reddest, thanks for ur reply.
08/26/2007 - 16:38
Hello, thank you for this tutorial. I tried to try the cropping funtion but it seems like I missed something and it's not working.
Here is the code:
string filename, ImageFormat format)
{
Image img = CaptureWindow(handle);
img = cropImage(img,new Rectangle(0, 42, 847, 450));
//img = resizeImage(img, new Size(760, 526));
img.Save(filename, format);
}
the cropImage in my code is same from the cropImage method here.
Thank you!
08/26/2007 - 17:03
Kim, you code looks fine. The problem is I don't know what output you're expecting. Can you be more specific on what exactly isn't working? Is it cropping incorrectly, or not cropping at all? I just ran the crop code on the flower image above and everything seemed to work fine.
08/29/2007 - 07:09
Great work, thanks!
11/02/2007 - 21:35
Hey, Hows it going, I have a very newby type of question. When I try to run this in Visual studio, I get "Error while trying to run project,unable to start debugging, Binding handle is invalid"
thanks
11/02/2007 - 21:48
It sounds like there is a problem with your Visual Studio settings. I don't have any experience with that error myself, but here's an MSDN forum that seems to address a similar problem.
Unable to debug: The binding handle is invalid.
Hopefully that helps a little.
11/03/2007 - 00:05
That did it, I was able to find the link below from your link. It was due to the Terminal Services being disabled. They say it has been fixed in vs sp1 -more info at the link below if anyone needs it. THANKS AGAIN
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105751
11/06/2007 - 12:50
Another newbie question; When I upload the files to a server, and attempt to open the page, the application file is displayed as xml source code in the browser. I am using apache/fed core 3, Do I need to install some sort of xml parsing module?
thanks
01/03/2008 - 13:39
Thanks for the Post, it really helped. I'm working on a project using WIA, I scanned a documents and need to CROP out 4 different areas.
How can I determine the Rectangle of each area by simply Loading the Scanned Image in a picture box and dragging my mouse over each area like in Microsoft Paint?.
This will really save me from the over head of using WIA to scan and crop for each area.
02/18/2008 - 23:49
Thanks a lot...Great tutorial !
02/23/2008 - 02:06
{
if (FileUpload1.HasFile == true)
{
if (FileUpload1.PostedFile.ContentType == "image/pjpeg")
{
FileUpload1.PostedFile.SaveAs(Server.MapPath(
"./upload/" + FileUpload1.FileName));
Label1.Text = "file saved";
}
}
else
{
Label1.Text = "cant save";
}
}
this code is upload the image
and i want to resize the image after uploading so pla give me code ans
02/23/2008 - 11:53
After the image has been uploaded, it's in the hands of your server code. If your server is written in ASP.NET, you can use the same code that's in this post. If your server is written in another language, you'll have to do some searching on how to resize images with your specific language.
03/03/2008 - 08:56
Saved me a few hours and from having to use a Graphics object to do cropping. Cheers muchly
03/06/2008 - 14:40
Thank you!
Finally!
A way to crop and flip my background image!
Great tutorial!
03/06/2008 - 22:59
Awesome! I was trying to figure out how to use the Developer's Image Library (DevIL). All I wanted was to be able to open, resize, crop, and save a picture, so It seemed way overkill to use their library. Your tutorial is exactly what I wanted! Thanks!
03/21/2008 - 08:47
Excellent snippet of code. Explained everything clearly and saved me a couple of hours of work. Much appreciated
03/26/2008 - 08:29
Thanks for this very useful resizeImage method.
03/30/2008 - 19:16
Thanks a lot!! I was looking for something like this for my project.
04/15/2008 - 19:02
How come the gif loses its animation if cropped?
04/16/2008 - 01:12
how can i save a rectangle as xml data.
g.drawrectangle(...);
i want to save this rectangle
05/14/2008 - 23:50
Thanks very much for the code. I integrated it into something I was doing for some staff at work who wanted to be able to re-size images simply. I threw a little c# application together and it works pretty well.
One issue i do have it that the GDI+ component seems to fail if the image is non-colour managed. In other words, I can use it for RGB/8 (8 bit RGB images) but other colour spaces (like RGB/8# - unmanaged) causes a GDI+ error.
Does anyone have any experience in that area?
The downside for me is that my application only works with some jpgs - not all jpgs.
Thanks again for the code. Very cool and useful for people new to it all (like I am)
Cliff
05/16/2008 - 08:16
Thank you so much! Well done!
06/12/2008 - 00:54
So cool!
06/21/2008 - 11:01
great article
but i want to know how can i use the code to resize certain image to fixed width (100 for example) and keeping the height proportional?
06/23/2008 - 02:56
thx2u
06/25/2008 - 02:21
Thank you for this great code. I'm having one odd problem though, and if anyone has any ideas I'd be grateful.
My problem is that after calling resizeImage, my original source file is locked. So when the user modifies the image and tries to save it, I can't overwrite the original image (my goal).
Here's my client usage snippet:
img = imageResize(img, new Size(100,100));
img.Save(destfile));
img.Dispose();
When I bypass the resize method and simply do a File.Copy(src,dst), the source file is not locked. I've spent two days trying to work around this--it's killing me.
I think the issue is related to the "redefinition" of "img". It is allocated in the client code (new Bitmap(source)), then more space is allocated in resizeImage as "b" (thumbnail Image), then "b" is returned and assigned to "img". Is there an orphaned IO stream for the first "img" allocation that holds an open handle to the source file?
This problem is a bit over my head, so any help would be awesome! Thanks.
I'm on ASP.NET, Framework 3.5, IIS6, Win 2k3 server
06/25/2008 - 09:24
Update regarding my previous comment: My problems don't appear to have anything to do with imageResize(). I'll keep chugging along in search of a solution.
Regarding quality of the created thumbnail, I have to say it's stunning.
01/27/2010 - 17:03
John
I had the same problem with the handle to the source image remaining open and what solved for me was forcing the Graphics instance to be released.
{
}
Hope this helps.
Javier
07/13/2008 - 00:43
Thanks! This is just what I've been looking for.
Oh, the time this could have saved me in the past!
07/23/2008 - 21:06
Love the tutorial. One question, though. You supply a cropping routine, which is wonderful, but one thing that would be of great interest to me is a tutorial about selecting the image to be cropped. There seems to be few good examples of selecting a rectangle on the screen a la Windows Paintbrush or Photoshop. Any ideas where I might find such an example?
07/30/2008 - 10:34
This is cool!!!
Thanks mannnnn, that is what I am talkin about!
08/27/2008 - 13:37
Thanks man!
09/01/2008 - 04:23
Simple and beautiful....
09/09/2008 - 06:40
smple the best
09/10/2008 - 09:41
Thanks a lot. Keep up the good work. This resize method was exactly what I needed.
God Bless
09/11/2008 - 21:19
many thanks
09/15/2008 - 19:31
how am i suppose to do multiple upload of files?? can you guys help me?
09/23/2008 - 22:21
terific tutorial i ve gained lot of knoweledge by thius
09/26/2008 - 18:24
Terrific site. I was in the deep woe.but now i found my requiremetns
Lot of Thanks for code
10/03/2008 - 03:11
Hi,
I have a TIFF image whose background color is Black and the text i.e the foreground color is in white. I want it to be changed to White background and Black foreground. can you please help me on how to achieve this?
11/11/2008 - 22:52
Thanks a lot for that code....
11/20/2008 - 14:19
Thanks for the code, I tried a lot of examples but this one does exactly what I wanted.
12/11/2008 - 09:10
I save PNG image from RTF file.
All possible resizing-cropping-saving with this excellent code leave image in a strange aspect.
It is like elements (characters from “symbol font”) are too near between them…
Someone can help me?
12/14/2008 - 23:22
thanks sir u hve done good job.
03/09/2009 - 13:19
Thanks! Hundreds of images resized at the click of a button; it's a beautiful thing. This is awesome.
04/22/2009 - 01:41
Good code, just one thing: Avoid calling dispose yourself, use a using-block:
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
it's not 100% necessary, but it's good pratice, and if you felt you should call dispose, you might as well use using.
07/05/2009 - 12:24
There is a useful ActiveX control called AccessImage.
It does all the work about images for you.
FOR DEVELOPER: binds to database field (if needed), auto resizes big images, can manage pics in external storage, generates previews.
FOR END USER: load from file, paste from clipboard, scan or drag n drop image in 1 click. Crop it right on the form. Undo if something goes wrong.
Watch action video here: http://access.bukrek.net/tutorial/action-video/
08/25/2009 - 22:29
you all are the best, I have been trying to write an implementation of an image resizing and cropping algorithm, using VS2005. Email me any code at bpgueze@hotmail.com
11/17/2009 - 13:23
BTW, change this:
if (nPercentH < nPercentW)
to this:
if (nPercentH > nPercentW)
if you want to superscribe the image to the cliprect. This code inscribes the image to the cliprect.
12/28/2009 - 13:02
thanks
01/04/2010 - 17:12
Hi everyone. The issue we’re having is we have a wpf richtextbox, and we’re pasting images into it, but we want to be able to limit the physical data size, not the display size of the images being pasted in. In other words, if a user paste in an image that’s 2MB, we want to automatically shrink it down to a more manageable size. We have to have many users who share richtextbox data. So their text and images gets saved up to a cloud database so other users may download it. Please note that when an image gets pasted in, it’s a System.Windows.Controls.Image object.Any help will be greately appreciated
01/07/2010 - 14:30
I'm using the cropping code, and I'm getting an outOfMemoryException error.
picMotion.Image = (Image)frame.Clone(new Rectangle(xStart, yStart, frame.Width, frame.Height), frame.PixelFormat);
I don't even know where start with this.
01/29/2010 - 04:09
Are the X and Y values legit? i.e. is the new Rectangle within the frame image dimensions?
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.