When working on the web whether it be a full blown CMS or a small product cart. The issue of how to upload images, and especially resize them to fit your site comes up quite a bit. C# has a useful image library that you can use to resize your images to fit your needs. This post will show you how to upload the file, manipulate it, and then save it so that it can be used where you need it.
For this post we are going to make a *very* simple image gallery. Our image gallery will only have one “default” album and display the thumbnails of all of the images. In a later post I will implement the functionality to view larger sizes of the images (using some pretty cool JQuery plugins).
The Spec:
We want to upload images and resize them to 2 different sizes, Thumbnails and the large size image. We do not want to store the images themselves in a database; we do however, want to persist the image location into the database. And finally we need a page to display all the thumbnails and link to the full size images.
Step One:
First we are going to create our data structure to hold our images and other data. In the database we are going to create a table with 4 columns.
We will be storing the image title and relative web paths to the thumbnail and the full size image here. We also need to create our directory structure where the files will actually be stored in our web root. Here we are storing our images in the "UserImages” folder and subfolders.
Step Two:
We need to create a page where we will upload our files. Right Click on your web project and add a new aspx page. You will need to add a file upload control and text boxes for all of the properties you would like to store in the database (in our case, just the Title).
<form id="form1" runat="server">
<div class="field">
<asp:Label ID="ImageTitle" runat="server" AssociatedControlID="ImageTitleText">Image Title:</asp:Label>
<asp:TextBox ID="ImageTitleText" runat="server"></asp:TextBox>
</div>
<div class="field">
<asp:Label ID="ImageValue" runat="server" AssociatedControlID="ImageValueFile">Image:</asp:Label>
<asp:FileUpload ID="ImageValueFile" runat="server" />
</div>
<div class="buttons">
<asp:Button ID="Submit" runat="server" Text="Save Image" OnClick="SaveImage_Click" />
</div>
</form>
If you are doing this in a production environment you would want to secure this page somehow. For our purposes we are just going to leave the page unsecure. Also, notice that we only have one file upload control on the page. We don’t want to have to resize each of our images ourselves in Photoshop, or worse wait for someone else to do it. We are going to have our website do it for us.
Step Three:
Here is where we get to the meat of this post. We need to decide what size of images we want. For our purpose we want to keep the aspect ratio of the images as they are uploaded. We do not want to crop them to “all be square images.” So we are going to resize our images to have a max thumbnail size of 150 x 150 and a max large size of 500 x 500 (just in case anyone tries to upload a file straight from their digital SLR). Here is our button click event
protected void SaveImage_Click(object sender, EventArgs e)
{
// First check if there is a file present.
// Should also check that the file is an allowed type.
if (ImageValueFile.HasFile)
{
// We have a file. Save the image
if (SaveImage(ImageValueFile.PostedFile, ImageTitleText.Text))
Response.Write("Your Image Has Been Saved");
else
Response.Write("There was an error in saving your image.");
}
And the SaveImage function that it calls
public bool SaveImage(HttpPostedFile image, string title)
{
bool result = false;
int MaxWidth = 500;
int MaxHeight = 500;
int ThumbMaxWidth = 150;
int ThumbMaxHeight = 150;
// Ensure a unique filename
string upFileName = new Guid().ToString() + image.FileName.Substring(image.FileName.LastIndexOf("."));
// Should put this into a config file.
string LargeFile = @"UserImages\Large\" + upFileName;
string ThumbFile = @"UserImages\Thumbs\" + upFileName;
try
{
System.Drawing.Image UploadedImage = System.Drawing.Image.FromStream(image.InputStream);
System.Drawing.Image LargeImage = ImageTool.ToMaxSize(UploadedImage, MaxWidth, MaxHeight);
System.Drawing.Image ThumbImage = ImageTool.ToMaxSize(UploadedImage, ThumbMaxWidth, ThumbMaxHeight);
LargeImage.Save(Request.PhysicalApplicationPath + LargeFile);
ThumbImage.Save(Request.PhysicalApplicationPath + ThumbFile);
}
catch (Exception ex)
{
return false;
}
GalleryDataContext db = new GalleryDataContext();
// Save the image paths and title to the database using LINQ
GalleryImage i = new GalleryImage();
i.FullSize = LargeFile.Replace('\\', '/');
i.Thumbnail = ThumbFile.Replace('\\', '/');
i.Title = title;
try
{
db.GalleryImages.InsertOnSubmit(i);
db.SubmitChanges();
}
catch (Exception ex)
{
return false;
}
return result;
}
The only real thing this function does is convert the posted file into a System.Drawing.Image and then call a utility class that will do the actual resizing ( lines 18 - 20 ). Everything after that is just a LINQ expression to insert the paths to the database. The function ImageTool.ToMaxSize is as follows:
public static Image ToMaxSize(Image image, int maxWidth, int maxHeight)
{
int newWidth = 0;
int newHeight = 0;
int currentWidth = image.Width;
int currentHeight = image.Height;
if ((currentWidth / (double)maxWidth) > (currentHeight / (double)maxHeight))
{
newWidth = maxWidth;
newHeight = Convert.ToInt32(currentHeight * (maxWidth / (double)currentWidth));
if (newHeight > maxHeight)
{
newWidth = Convert.ToInt32(maxWidth * (maxHeight / (double)newHeight));
newHeight = maxHeight;
}
}
else
{
newWidth = Convert.ToInt32(currentWidth * (maxHeight / (double)currentHeight));
newHeight = maxHeight;
if (newWidth > maxWidth)
{
newWidth = maxWidth;
newHeight = Convert.ToInt32(maxHeight * (maxWidth / (double)newWidth));
}
}
Bitmap newImage = new Bitmap(newWidth, newHeight);
newImage.SetResolution(72, 72); //web resolution;
//create a graphics object
Graphics gr = Graphics.FromImage(newImage);
//just in case it's a transparent GIF force the bg to white
SolidBrush sb = new SolidBrush(System.Drawing.Color.White);
gr.FillRectangle(sb, 0, 0, newImage.Width, newImage.Height);
//Re-draw the image to the specified height and width
gr.DrawImage(image, 0, 0, newImage.Width, newImage.Height);
return newImage;
}
Here we are doing some math to see which is larger, the width or the height. It will scale the image down by the largest value to get the original smaller value “within the range” that we want. Then we create a new Bitmap object with our new width and height. Finally we use the .NET graphics library to paint our canvas white and scale our uploaded image into that newly painted canvas.
Final Step:
At this point we have the images saved to our web server and the relative paths stored in the database. Now all we need is a page to display the thumbnails. I will show this in my next post where I will also display the images using some JQuery plugins. I will post all my code at the end of the next post.
ASP.NET, SQL Server, General, LINQ
image manipulation, images, file upload, jquery