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

Program for Optimization and Resizing of an Image

By , 31 Mar 2010
 
ImageOptimizationnResize

Introduction

In today's websites, we often need to save images from users whether to create personal galleries or product galleries, etc. Simultaneously we don’t want to limit user’s right to upload a certain type of image of a certain quality most of the time. That is, the user can upload any common format of image (.jpg, .gif, .bmp or .png) and/or Dimensions of image and/or Size of Image (in bytes). Then the whole process of optimization has gone to be internal, to process image and convert that into a specific format, specific dimensions, also you can watermark an image programmatically. Here in this context, I want to describe about changing the dimensions of image and side by side image is optimized for size (in bytes). For getting reference about other topics like format conversion and watermarking, please visit the links listed at the end of this article.

Using the Code

For this program to work, inclusion of these four namespaces is required:

using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

The first one is used to access ‘Path’ class through which we extract the extension of uploaded image. Next, it is required to use other image processing related classes like ‘Bitmap’, ‘Graphics’, ‘StringFormat’, etc. The third one provides us the flexibility of choosing a format for our resultant image, and the fourth one is used to keep the quality of image intact using interpolation operations.

In my demonstration program, there are two blank directories ‘Original Images’ and ‘Resultant Images’. The former is for saving original images and the latter is for optimized and resized images. There is a Default.aspx page. Six ASPX controls have been put there.

  • FileUpload: To upload image file that has to be processed
  • TexBox1: Used to specify the width of the resultant image (in pixels)
  • TexBox2: Used to specify the height of the resultant image (in pixels)
  • Button: Used to trigger the operation of processing
  • Image1: Used to show the original Image
  • Image2: Used to show the resultant Image

Also there are other controls which have been used for furnishing the data about images.

Once your image has been processed, both of your images (original & resultant) will be shown in Image1 and Image2 controls respectively. Data specific to each image (width, height, size in bytes) will be shown along with the images.

The handler function of the button clicking which the image has been processed for optimization and resizing is given below:

protected void btnResults_OnClick(object sender, EventArgs e)
{
    if (Page.IsValid && fpImage.HasFile)
    {
        string tmpName = Guid.NewGuid().ToString();
        fpImage.SaveAs(MapPath("~/Original Images/" + 
		tmpName + Path.GetExtension(fpImage.FileName)));
        imgOriginal.ImageUrl = "~/Original Images/" + 
		tmpName + Path.GetExtension(fpImage.FileName);

        Bitmap original_image = new Bitmap(fpImage.FileContent);
        lblOIW.Text = original_image.Width.ToString();
        lblOIH.Text = original_image.Height.ToString();
        lblOIS.Text = fpImage.FileContent.Length.ToString();
            
        OptimizeNResize(original_image, tmpName);
        if(original_image != null) original_image.Dispose();
    }
}

I create a new GUID and collect it in a string variable tmpName. This is the name to save the original as well as optimized image. The next line is to save the original image to ‘Original Images’ folder. This saved image is then linked to an Image control on page.

The image is now collected in a new Bitmap and this bitmap. The dimensions and size of original images has been shown along with it. Now the bitmap of the original image and tmpName are passed to a new function which is responsible for optimizing this image. This function is as under:

protected void OptimizeNResize(Bitmap original_image, string tmpName)
{
    Bitmap final_image = null;
    Graphics graphic = null;
    int reqW = Int32.Parse(txtWidth.Text);
    int reqH = Int32.Parse(txtHeight.Text);
    final_image = new Bitmap(reqW,reqH);
    graphic = Graphics.FromImage(final_image);
    graphic.FillRectangle(new SolidBrush(Color.Transparent), 
		new Rectangle(0, 0, reqW,reqH));
    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic; /* new way */
    graphic.DrawImage(original_image, 0, 0, reqW, reqH);
    final_image.Save(MapPath("~/Resultant Images/" + tmpName + 
		Path.GetExtension(fpImage.FileName)));
    imgResult.ImageUrl = "~/Resultant Images/" + tmpName + 
		Path.GetExtension(fpImage.FileName);
    lblRIW.Text = final_image.Width.ToString();
    lblRIH.Text = final_image.Height.ToString();
    FileInfo nfi = new FileInfo(MapPath("~/Resultant Images/" + 
		tmpName + Path.GetExtension(fpImage.FileName)));
    lblRIS.Text = nfi.Length.ToString();

    lnkSave1.NavigateUrl = "~/Original Images/" + tmpName + 
		Path.GetExtension(fpImage.FileName);
    lnkSave2.NavigateUrl = "~/Resultant Images/" + tmpName + 
		Path.GetExtension(fpImage.FileName);

     if (graphic != null) graphic.Dispose();
     if (original_image != null) original_image.Dispose();
     if (final_image != null) final_image.Dispose();
}

The first few lines of the above function are used to specify variables of Bitmap and Graphics classes. Width and height of resultant image have been extracted from textboxes and a blank bitmap has been created of the same dimensions. This bitmap has now been formed into an image and collected in a graphic variable.

The above graphic has now been filled with a rectangle of transparent background. Interpolation operation has been applied to keep the quality of image intact and then the original image has been drawn on this graphic. This graphic originally is a reference to a Bitmap object (final_image). Now the final image has been saved in a resultant image folder and shown int the image2 control with the specific values (width, height, and size) mentioned along with it.

However, I have made the dimensions of controls image1 and image2 fixed on page. But the dimensions of image contained could be different. I have put two links on page which will show images in actual sizes in new browser windows.

Finally all the containers of images, original image bitmap, final image bitmap and graphics object have been disposed and we get an image optimized in size with the required dimensions.

Points to Ponder

The practical stuff is attached as a demo. You will easily understand when you look at the download files. Image processing operations require high amount of server resources, if not managed properly, they can slow down the performance. It is important to release resources by disposing the objects of classes like Bitmap, when you're done. You might also be interested in some other articles that I have written:

Final Words

I hope you find the stuff helpful. Thanks for reading. Good luck!

History

  • 31st March, 2010: Initial post

License

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

About the Author

Mohd Arshad (Sam)
Software Developer (Senior) Cherisys Technologies, WebStreet.in
India India
Member

Software professional with demonstrated strength in windows-based and web-based software development. Have 4 years of experience with the full software development lifecycle including requirements, design, development, testing/QA, deployment, training & support. Have 1 year experience managing groups, planning and executing implementations. Practical working knowledge of all aspects of IT. Possess strong insight into practical business considerations.



www.cherisys.com
www.webstreet.in
www.codevdo.com
www.bizkut.com

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   
GeneralMy vote of 5membermanoj kumar choubey26 Feb '12 - 21:25 
Nice
GeneralokaymemberYves8 Apr '10 - 14:50 
So you redraw the image to smaller size. What if the source bitmap is BMP .. do you still save it as BMP type ?
Maybe redimension and make sure the reult image is JPEG would be optimal, am i wrong ?
Questionone questionmemberdamdam1011 Apr '10 - 6:46 
I have one question regarding your article,
 
I want to save processed image in database rather than saving it into a folder.
But i did not find any method or property through which I can get the bytes of final image bitmap
(just like we use FileBytes property of FileUpload control to get bytes of file)
 
Please guide me what to do for getting bytes of final image.
Thanks in advance
AnswerRe: one questionmemberMohd Arshad (Sam)1 Apr '10 - 7:07 
Hello damdam, hope you're fine...
 
You need to use some container of byte stream and then get the bytes from this container.
As I have already suggested to add namespace System.IO in my example.
There is a class in this namespace, it is MemonyStream.
 
Use an object of this class to collect byte stream of final image like this:
 
MemoryStream mStream = new MemoryStream();
final_image.Save(mStream,ImageFormat.Jpeg);
 
Then use this statement to get byte array (byte[])... same as you get using the property of FileBytes:
 
mStream.GetBuffer();
 
You can now save your image to database.
One more thing which you must keep in mind is to dispose this object when you're done...
... as I have also suggested to dispose most of the objects of Image Classes.
To dispose you need to write a simple statement as below:
 
if (mStream != null) mStream.Dispose();
 
This helps to release the resources of system and improve performance.
 
Once again thanks for your appreciations.
 
Good Luck!
GeneralRe: one questionmemberdamdam1013 Apr '10 - 0:57 
thank you very much mohd, I have made it happen just because of your help.
 
regards
Damiz
GeneralRe: one questionmemberMohd Arshad (Sam)3 Apr '10 - 1:03 
Glad to help Smile | :) Smile | :)
 
Good Luck!
QuestionQuestionmemberdamdam1011 Apr '10 - 6:40 
I have one question regarding your article,
 
I want to save processed image in database.
But i did not find any method or property through which I can get the bytes of final image bitmap.
Please guide me what to do for getting bytes of final image.
 
Thanks in advance
AnswerRe: QuestionmemberMohd Arshad (Sam)1 Apr '10 - 7:09 
I have already answered same question above...
... and hope you got the idea.
 
Good Luck
GeneralNice workmemberdamdam1011 Apr '10 - 6:36 
This is really a cool solution. I was looking for such example so long.
Thanks for uploading
 
Regards
Damiz
GeneralRe: Nice workmemberMohd Arshad (Sam)1 Apr '10 - 6:57 
Glad to help
Keep it coming Smile | :)
GeneralMy vote of 1membervilainchien31 Mar '10 - 22:42 
The articles you post are pretty much just reinterpretations of basic
GeneralRe: My vote of 1memberMohd Arshad (Sam)1 Apr '10 - 3:06 
Then why don't you write an upgraded/advance version of it...
... so that at least one article could be added in list of your contributions which is 0 at present.
 
Before pointing your finger on others works at least make some reputation/some class. Your reputation is no more than just by casting votes of 1s or 2s. Shame on you people....
GeneralMy vote of 1memberPCoffey31 Mar '10 - 11:01 
based on your responses to peoples rating, on this article and others, i would guess that you are writting articles that will generate a negative response only so you can be rude to the responder.
 
there are other ways to troll the internet.
GeneralRe: My vote of 1 [modified]memberMohd Arshad (Sam)31 Mar '10 - 12:59 
There are many people at codeproject who create offense not only once or twice but thrice...
... and I think should not be ignored for long time.
 
Lets have a look on the reputation of people as debater, participants or authors...Such people are not found with any worthy contributions to codeproject rather than casting votes of 1 or 2. I suggest them at least make some worthy contributions before pointing your finger towards others works.
modified on Wednesday, March 31, 2010 7:10 PM

RantMy vote of 1memberPogoboyMtK31 Mar '10 - 9:15 
It is the ignorance of a novice developer who thinks far too much of themselves that results in the disrespectful arrogance shown here. If this guy truly leads a team of developers, I really, really feel sorry for them.
 
BTW. The articles you post are pretty much just reinterpretations of basic "get started" tutorials on the given topics. You are capable of creating a good article. I've read all of them and you have produced one good one so far. Take your time and produce those. They are worthy of being on CP, not stuff like this one.
And for G** sakes, please show some class.
GeneralRe: My vote of 1memberMohd Arshad (Sam)31 Mar '10 - 13:10 
There are many people at codeproject who create offense not only once or twice but thrice..
... and I think should not be ignored for long time.
 
Lets have a look on the reputation of people as debater, participants or authors...Such people are not found with any worthy contributions to codeproject rather than casting votes of 1 or 2. I suggest them at least make some worthy contributions before pointing your finger towards others works.
GeneralRe: My vote of 1memberYves8 Apr '10 - 14:39 
You are pretty right Mohd. Some peoples here at CodeProject have a fast trigger to give a poor vote.
This is why i hesitate a lot before posting an article. How ever keep the good work.Thumbs Up | :thumbsup:
GeneralPreserving Aspect RatiomemberMohammad Elsheimy31 Mar '10 - 7:30 
What about giving just the width and the code calculates the height and the opposite?
Regards,
Mohammad Elsheimy
 
---------------------------
Just Like a Magic
http://JustLikeAMagic.Wordpress.com

GeneralRe: Preserving Aspect RatiomemberMohd Arshad (Sam)31 Mar '10 - 13:27 
Hello brother, hope you're fine...
 
Thanks for your appreciations. Yes you can maintain the aspect ratio just by specifying only one dimension of resulting image...
 
If you choose to specify width, calculate the height using statement given below:
 
int reqH = (reqW * original_image.Height) / original_image.Width;
 
and if you choose to specify height, calculate the with using statement given below:
 
int reqW = (reqH * original_image.Width) / original_image.Height;
 
Once again grateful for your words about all my work. Thanks a lot!
GeneralRe: Preserving Aspect RatiomemberDimitris Vassiliades31 Mar '10 - 15:16 
Το make sure it will fit in given sizes, and preserve aspect ratio you can also do
int scaleFactor = Math.Min( reqW/original_image.Width, reqH/original_image.Height );
reqW *= scaleFactor;
reqH *= scaleFactor;

...Plug & Pray... Dead | X|

GeneralRe: Preserving Aspect RatiomemberMohd Arshad (Sam)31 Mar '10 - 20:40 
Hi there, hope you're fine...
Thanks for your suggestions.
GeneralRe: Preserving Aspect RatiomemberMohammad Elsheimy1 Apr '10 - 1:01 
Thanks alot.
 
Mohd, you deserves it. Thank you.
Regards,
Mohammad Elsheimy
 
---------------------------
Just Like a Magic
http://JustLikeAMagic.Wordpress.com

GeneralThings to be careful of...memberRene Pilon31 Mar '10 - 3:02 
In your OptimizeNResize method
 
int reqW = Int32.Parse(txtWidth.Text);
int reqH = Int32.Parse(txtHeight.Text);
 
if( (reqW > 0) && (reqH > 0 ) // make sure you have positive sizes
 
As well - just to be sure - I'd wrap that up in a try / catch....
 
Regards,
 
Rene Pilon
GeneralRe: Things to be careful of...memberMohd Arshad (Sam)31 Mar '10 - 3:16 
Hi dear Rene...
 
That has already been cared about...
... see demonstration program, client side validations are there to check positive numeric values between 50-999.
 
And because this article is about image processing, so i did not extensively mentioned about validations.
 
By the way, thanks for your interest to improve this article.
GeneralMy vote of 1memberTringXRay31 Mar '10 - 2:44 
This is a pointless piece of code and demonstartes nothing.

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 31 Mar 2010
Article Copyright 2010 by Mohd Arshad (Sam)
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid