Click here to Skip to main content
15,887,596 members
Articles / Web Development / ASP.NET

Dynamically resize uploaded images & save in PNG format

Rate me:
Please Sign up or sign in to vote.
4.80/5 (38 votes)
7 May 2003CPOL1 min read 412.9K   8.6K   161   39
Overcome the problem of image quality deterioration on resizing by converting to PNG format.

Sample Image - PNGUploader.jpg

Introduction

Uploading images & storing them dynamically after resizing is a painless affair now using .NET, unlike what it used to be in Classic ASP. There are several good articles on uploading & resizing images on CodeProject (.NET Image Uploading [^], File Upload with ASP.NET [^], Thumbnail Image Creation and Image format Conversion Utility [^]) & elsewhere on the net (True Image Resizing [^]). One issue with resizing images is that the quality of the image deteriorates. This article is written in praise of the PNG image format & shows how the original quality of the uploaded image of any regular format can be maintained & even be improved.

PNG - What's it?

Check out this excellent article on the PNG image format - FAQ: Converting GIF or JPG to PNG [^]. To paraphrase the article -

  • PNG stands for Portable Network Graphics and pronounced "ping".
  • PNG is supported by the major browsers (Microsoft IE and Netscape 4.x and higher)
  • The images are a lot clearer, no more grainy GIF images or pixelated JPGs!

Source code

This application allows the user to set the dimensions for the image to be resized & uploaded. The resized image is converted into the W3C Portable Network Graphics (PNG) image format by using the PNG property of the ImageFormat class.

C#
<%@ Page Language="C#" %>
<%@ import Namespace="System.Drawing.Imaging" %>
<script runat="server">
//Pics folder has to be created under the current folder
void UploadBtn_Click(Object sender, EventArgs e)
{      
    String UploadedFile = MyFile.PostedFile.FileName;
    int ExtractPos = UploadedFile.LastIndexOf("\\") + 1;
  
    //to retrieve only Filename from the complete path
    String UploadedFileName = UploadedFile.Substring(ExtractPos,UploadedFile.Length - ExtractPos);
       
    // Display information about posted file. Div is invisible by default   
    FileName.InnerHtml = UploadedFileName;
    
    MyContentType.InnerHtml = MyFile.PostedFile.ContentType;
    
    ContentLength.InnerHtml = MyFile.PostedFile.ContentLength.ToString();
    
    FileDetails.Visible = true; //div is made visible
 
    // Save uploaded file to server at the in the Pics folder
    MyFile.PostedFile.SaveAs(Request.PhysicalApplicationPath 
                            + "pics\\" + UploadedFileName );

   //thumbnail creation starts
   try
   {
      //Retrieve the image filename whose thumbnail has to be created
      String imageUrl =  UploadedFileName;
      //Read in the width and height
      int imageHeight =Convert.ToInt32(h.Text);
      int imageWidth  = Convert.ToInt32(w.Text); 
  
      //You may even specify a standard thumbnail size
      //int imageWidth  = 70; 
      //int imageHeight = 70;
  
      if (imageUrl.IndexOf("/") >= 0 || imageUrl.IndexOf("\\") >= 0 )
      {
         //We found a / or \
         Response.End();
      }
  
      //the uploaded image will be stored in the Pics folder.
      //to get resize the image, the original image has to be
      //accessed from the Pics folder
      imageUrl = "pics/" + imageUrl;
  
      System.Drawing.Image fullSizeImg 
              = System.Drawing.Image.FromFile(Server.MapPath(imageUrl));
      System.Drawing.Image.GetThumbnailImageAbort dummyCallBack 
              = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
      System.Drawing.Image thumbNailImg 
              = fullSizeImg.GetThumbnailImage(imageWidth, imageHeight, 
                                              dummyCallBack, IntPtr.Zero);
   
      //We need to create a unique filename for each generated image
      DateTime MyDate = DateTime.Now;
  
      String MyString  = MyDate.ToString("ddMMyyhhmmss") + ".png" ;
 
      //Save the thumbnail in PNG format. 
      //You may change it to a diff format with the ImageFormat property
      thumbNailImg.Save ( Request.PhysicalApplicationPath 
                          + "pics\\" +   MyString , ImageFormat.Png);
      thumbNailImg.Dispose();
   
      //Display the original & the newly generated thumbnail
   
      Image1.AlternateText = "Original image";  
      Image1.ImageUrl="pics\\" + UploadedFileName;
      Image2.AlternateText = "Thumbnail";
      Image2.ImageUrl="pics\\" + MyString;
   }
   catch(Exception ex)
   {
      Response.Write("An error occurred - " + ex.ToString());
   }
}
  
//this function is reqd for thumbnail creation
public bool ThumbnailCallback()
{
   return false;
}
</script>

How to run the app

Unzip & run the .aspx file using IIS. Make sure a folder named PICS is created before-hand in the current working directory.

Conclusion

This article demonstrates how the quality of dynamically created images can be maintained & even enhanced by saving them in PNG format.

License

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


Written By
Architect
India India
'Anil' Radhakrishna is a seasoned architect who enjoys working with Microsoft tools & technologies. He blogs quite regularly about his little discoveries and technical experiments on his blog called Tech Tips, Tricks & Trivia. He loves building mash-ups using public Web APIs.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Abhishek Pant15-Jun-14 23:44
professionalAbhishek Pant15-Jun-14 23:44 
GeneralMy vote of 1 Pin
rhandler27-Dec-10 10:02
rhandler27-Dec-10 10:02 
GeneralMy vote of 1 Pin
amit.comp120-Dec-10 23:50
amit.comp120-Dec-10 23:50 
General1 problem Pin
barbod_blue22-Feb-08 18:06
barbod_blue22-Feb-08 18:06 
AnswerRe: 1 problem - solution Pin
johannesnestler11-Nov-08 23:33
johannesnestler11-Nov-08 23:33 
GeneralRe: 1 problem Pin
AprNgp23-Mar-09 5:21
AprNgp23-Mar-09 5:21 
Questionwonderful script Pin
danielix7-Dec-07 4:42
danielix7-Dec-07 4:42 
QuestionPNG 8Bit C# Pin
vitor.duarte18-Dec-06 0:55
vitor.duarte18-Dec-06 0:55 
QuestionVisual Basic Code Pin
KMOwen28-Oct-06 19:58
KMOwen28-Oct-06 19:58 
QuestionPNG Uploader - Overwrite Pin
dwhite0225-Oct-06 20:34
dwhite0225-Oct-06 20:34 
GeneralThe process cannot access the file "D:\test\pics\top.jpg" because it is being used by another process. Pin
shyrik15-Sep-06 13:35
shyrik15-Sep-06 13:35 
GeneralRe: The process cannot access the file "D:\test\pics\top.jpg" because it is being used by another process. Pin
Chris Cameron29-Nov-06 12:34
Chris Cameron29-Nov-06 12:34 
GeneralRe: The process cannot access the file "D:\test\pics\top.jpg" because it is being used by another process. Pin
GerryHeidenreich27-Sep-07 5:06
GerryHeidenreich27-Sep-07 5:06 
GeneralPoor quality after resize Pin
edika9926-Feb-06 7:53
edika9926-Feb-06 7:53 
GeneralWhy the Dummy CallBack Pin
emadadelme9-Feb-06 2:31
emadadelme9-Feb-06 2:31 
GeneralUpload, Resize and Thumbnails Pin
zioturo2-Nov-05 0:31
zioturo2-Nov-05 0:31 
GeneralRe: Upload, Resize and Thumbnails Pin
gauty11-Jan-06 23:04
gauty11-Jan-06 23:04 
GeneralI have this problem Pin
pmore27-Oct-05 0:44
pmore27-Oct-05 0:44 
GeneralResize Images Problems Pin
gmachado0821-May-05 3:18
gmachado0821-May-05 3:18 
Generalmore universal resizing solution Pin
Anonymous3-Apr-05 10:50
Anonymous3-Apr-05 10:50 
Generalgood article, but i have a better solution Pin
Anoynomus19-Oct-04 16:41
sussAnoynomus19-Oct-04 16:41 
this spraked my interest and as another viewer noted, the .net thumbnail thing doesn't work correctly with certian images. i have created a page that uploads the image and sizes it while keeping the proportions the same. here is the code, sub-optimal i'm sure.. but whatever... Poke tongue | ;-P


<code><%@ Page Language="C#" %>

<%@ import namespace="System.IO" %>
<%@ import Namespace="System.Drawing.Imaging" %>
<%@ import Namespace="System.Drawing" %>

<script runat="server">

void Page_Load(Object sender, EventArgs e)
{

}

void UploadBut_Click(Object sender, EventArgs args)
{
String FilePath = Request.PhysicalApplicationPath + "\\test\\";
String ImageName = "camp_2005";
Int32 ImageWidth = 190;
Stream ImageStream = PhotoUpload.PostedFile.InputStream;

if ( PhotoUpload.PostedFile.FileName != "")
{
SaveUploadImageAsJpeg(ImageStream, FilePath, ImageName, ImageWidth);
SaveUploadImageAsGif(ImageStream, FilePath, ImageName, ImageWidth);
SaveUploadImageAsPng(ImageStream, FilePath, ImageName, ImageWidth);
}
}

void SaveUploadImageAsJpeg(Stream ImageStream, String FilePath, String ImageName, Int32 ImageWidth)
{
String Extension = ".jpg";
String MimeType = "image/jpeg";
long Quality = 95;
UploadImage(ImageStream, FilePath, ImageName, ImageWidth, Extension, MimeType, Quality);
}

void SaveUploadImageAsGif(Stream ImageStream, String FilePath, String ImageName, Int32 ImageWidth)
{
String Extension = ".gif";
String MimeType = "image/gif";
long Quality = 100;
UploadImage(ImageStream, FilePath, ImageName, ImageWidth, Extension, MimeType, Quality);
}

void SaveUploadImageAsPng(Stream ImageStream, String FilePath, String ImageName, Int32 ImageWidth)
{
String Extension = ".png";
String MimeType = "image/png";
long Quality = 0; // has no effect on png files
UploadImage(ImageStream, FilePath, ImageName, ImageWidth, Extension, MimeType, Quality);
}

void UploadImage(Stream ImageStream, String FilePath, String ImageName, Int32 ImageWidth, String Extension, String MimeType, long Quality )
{
try
{
System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(ImageStream);

Int32 old_height = UploadedImage.Height;
Int32 old_width = UploadedImage.Width;

Int32 new_width = ImageWidth;
Int32 new_height = (Int32) Math.Ceiling( (old_height * new_width)/old_width );

Bitmap smallerImg = new Bitmap(new_width, new_height);
Graphics g = Graphics.FromImage(smallerImg);
g.DrawImage(UploadedImage, 0, 0, new_width, new_height);

UploadedImage.Dispose();

if ( !Extension.Equals(".png") )
{
EncoderParameters myParams = new EncoderParameters(1);
myParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, Quality );
smallerImg.Save( FilePath + ImageName + Extension, GetEncoderInfo(MimeType), myParams);
}
else
{
smallerImg.Save( FilePath + ImageName + Extension , ImageFormat.Png);
}
smallerImg.Dispose();
}
finally { }
}

private ImageCodecInfo GetEncoderInfo(string mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for(j = 0; j < encoders.Length; ++j)
{
if(encoders[j].MimeType == mimeType)
{
return encoders[j];
}
}
return null;
}

// Validate the uploaded file is an image (.jpg, .jpeg, .gif)
void ValidatePicture(Object src, ServerValidateEventArgs args)
{
args.IsValid = false;
String fileName = PhotoUpload.PostedFile.FileName.ToLower();
if (fileName == "" || (fileName.IndexOf(".jpg") > -1) || (fileName.IndexOf(".jpeg") > -1) || (fileName.IndexOf(".gif") > -1)) args.IsValid = true;
}

</script>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title></title>
</head>

<body>
<form id="MainForm" enctype="multipart/form-data" runat="server">
<table cellpadding="4" cellspacing="0" border="0">
<tr><td colspan="2" height="5"></td></tr>
<tr>
<td valign="top">Photo:</td>
<td><%
if ( new FileInfo(Application["PHYSICALPATH"] + "test/mytestImage.jpg").Exists )
{ %>
<div style="float:left; background-color:#666666; padding:1px;"><img src="../test/mytestImage.jpg" width="190"></div>
<div style="padding-top:8px; clear:both;"></div><br /> <%
}
if ( new FileInfo(Application["PHYSICALPATH"] + "test/mytestImage.gif").Exists )
{ %>
<div style="float:left; background-color:#666666; padding:1px;"><img src="../test/mytestImage.gif" width="190"></div>
<div style="padding-top:8px; clear:both;"></div><br /> <%
}
if ( new FileInfo(Application["PHYSICALPATH"] + "test/mytestImage.png").Exists )
{ %>
<div style="float:left; background-color:#666666; padding:1px;"><img src="../test/mytestImage.png" width="190"></div>
<div style="padding-top:8px; clear:both;"></div><br /> <%
} %>
<input id="PhotoUpload" runat="server" type="File" class="formcopy" />
<asp:customvalidator enableclientscript="false" cssclass="formcopy" display="dynamic" runat="server" text="* must be a .jpg, .jpeg, or .gif" controlToValidate="PhotoUpload" onservervalidate="ValidatePicture" />
</td>
</tr>
</table>
<br />
<table cellpadding="4" cellspacing="0" border="0">
<tr>
<td><asp:button ID="AddSaveButton" text="Upload" onclick="UploadBut_Click" cssclass="formcopy" runat="server" /></td>
<td></td>
</tr>
</table>
</form>
</body>
</html></code>
GeneralRe: good article, but i have a better solution Pin
Anoynomus22-Oct-04 3:14
sussAnoynomus22-Oct-04 3:14 
GeneralRe: good article, but i have a better solution Pin
Anonymous20-Feb-05 13:44
Anonymous20-Feb-05 13:44 
GeneralRe: good article, but i have a better solution Pin
Jeffrey Scott Flesher26-Jul-05 17:38
Jeffrey Scott Flesher26-Jul-05 17:38 
GeneralRe: good article, but i have a better solution Pin
bharathreddyd11-Jul-06 6:33
bharathreddyd11-Jul-06 6:33 

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.