• How to resize image and save to database in ASP.NET

    Posted on August 13, 2012 by in ASP.NET, C#, Dotnet

    User may upload an image of his choice, but we would need to store in different sizes/formats to suit our needs. We cannot request to user to supply image of all sizes, we need to accomplish this task on our own. In this article, I am going to explain in detail with an example on how to resize image and save to database.

    If you are interested in just saving image to database, take a look at below article.
    How to save image to database in ASP.NET 

    If you are new to using HttpHandlers, I would recommend you to read below article.
    Display Images from database in ASP.NET GridView using HttpHandler

    Database Connection
    Added following entry in web.config under connectionStrings element.

    <add name="Sql" connectionString="Data Source=(local); Initial Catalog=AdventureWorks; User=testuser; Password=testuser;" providerName="System.Data.SqlClient"/>

    Overview:
    We will create a simple ASP.NET webpage with a provision for the user to upload an image. The uploaded image will be resized and will be saved into the database as a thumbnail.

    Page Design:
    I have added an ASP.NET file upload control, button and an image control to the page. Clicking on the “Upload” button would create a thumbnail image from the upload image and then saves both images to the database. Later both images are retrieved from the database using HttpHandler and embedded into the imagecontrol.

    <div>
        <br /><asp:Label ID="lblFileName" runat="server" Text="File Name: "/>
        <asp:TextBox ID="tbxFileName" runat="server"/><br /><br />
        <asp:FileUpload ID="imgUpload" runat="server" CssClass="fileUploadStyle" />
        <br /><br />
        <asp:LinkButton ID="lnkUpload" Text="Upload" runat="server" OnClick="lnkUpload_Click"/>
    </div>
    <br /><asp:Label ID="lblThumbNail" runat="server" Text="ThumbNail Photo"></asp:Label>
    <br />
    <asp:Image ID="imgThumbNail" runat="server"/>
    <br />
    <asp:Label ID="lblLargePhoto" runat="server" Text="Large Photo"/>
    <br />
    <asp:Image ID="imgLarge" runat="server"/>
    

    Source Code:
    When the end user clicks the Browse button, a file dialog will open up.  User can navigate through the local file system to find the file to be uploaded to the server. When user clicks on the upload button, lnkUpload_Click event handler is raised. In the handler method, we initially check if the control has any file. A variable to store the content of the image is declared and initialized to a length of the content. The content from the file upload input stream is stored into the variable. A new variable “thumbnailImageBytes“ to store thumbnail photo is declared. ResizeImage function is invoked which would prepare a thumbnail photo from the actual image using .NET DRAWING API. Finally these attributes are passed to InsertProductPhoto method which will save this image into Production.ProductPhoto table of the database.

    protected void lnkUpload_Click(object sender, EventArgs e)
    {
        //check if file has been specified
        if (imgUpload.HasFile)
        {
            //variable to store the image content
            //the size of the variable is initialized to the file content length
            byte[] imageBytes = new byte[imgUpload.PostedFile.ContentLength];
    
            //Gets the underlying System.Web.HttpPostedFile object for a file that is uploaded
            //by using the System.Web.UI.WebControls.FileUpload control.
            HttpPostedFile uploadImage = imgUpload.PostedFile;
    
            //read the image stream from the post and store it in imageBytes
            uploadImage.InputStream.Read(imageBytes, 0, (int)imgUpload.PostedFile.ContentLength);
    
            //resize image to a thumbnail
            MemoryStream thumbnailPhotoStream = ResizeImage(imgUpload);
            byte[] thumbnailImageBytes = thumbnailPhotoStream.ToArray();
                           
            //insert the product photo
            int productPhotoID = InsertProductPhoto(tbxFileName.Text, imageBytes, thumbnailImageBytes);
    
            //set the url of the image to a custom http handler that would download the image and embed into it
            imgThumbNail.ImageUrl = "ProductImageHttpHandler.ashx?ProductPhotoID=" + productPhotoID + "&ImageType=thumbnail";
            imgLarge.ImageUrl = "ProductImageHttpHandler.ashx?ProductPhotoID=" + productPhotoID + "&ImageType=largephoto";
        }
    }
    

    In the ResizeImage function we load the content of the actual image into a bitmap object. The thumbnail dimensions are calculated based on the actual image’s aspect ratio. A new bitmap variable is initialized that would hold the thumbnail. A new graphics object is created from this bitmap. This graphics object is populated (or drawn) with content from the actual image. The content of the new bitmap object is written to the memory stream and returned to the upload event handler which would then fetch bytes from the stream and sent to InsertProductPhoto.

    private MemoryStream ResizeImage(FileUpload fileUpload)
    {
        // Create a bitmap with the uploaded file content
        Bitmap originalBMP = new Bitmap(fileUpload.FileContent);
    
        // get the original dimensions
        int origWidth = originalBMP.Width;
        int origHeight = originalBMP.Height;
        
        //calculate the current aspect ratio
        int aspectRatio = origWidth / origHeight;
        
        //if the aspect ration is less than 0, default to 1
        if (aspectRatio <= 0)
            aspectRatio = 1;
        
        //new width of the thumbnail image            
        int newWidth = 100;
        
        //calculate the height based on the aspect ratio
        int newHeight = newWidth / aspectRatio;
    
        // Create a new bitmap to store the new image
        Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
    
        // Create a graphic based on the new bitmap
        Graphics graphics = Graphics.FromImage(newBMP);
    
        // Set the properties for the new graphic file
        graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
    
        // Draw the new graphic based on the resized bitmap
        graphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);
    
        //save the bitmap into a memory stream
        System.IO.MemoryStream stream = new System.IO.MemoryStream();
        newBMP.Save(stream, GetImageFormat(System.IO.Path.GetExtension(fileUpload.FileName)));
    
        // dispose drawing objects
        originalBMP.Dispose();
        newBMP.Dispose();
        graphics.Dispose();
    
        return stream;
    }
    private System.Drawing.Imaging.ImageFormat GetImageFormat(string extension)
    {
        switch (extension.ToLower())
        {
            case "jpg":
                return System.Drawing.Imaging.ImageFormat.Jpeg;
            case "bmp":
                return System.Drawing.Imaging.ImageFormat.Bmp;
            case "png":
                return System.Drawing.Imaging.ImageFormat.Png;               
        }
        return System.Drawing.Imaging.ImageFormat.Jpeg;
    }
    

    In the InsertProductPhoto function, we have started by fetching connection string the configuration file. Once we have the connection string, we make a connection the database. We prepare a command object initialized with the connection and the insert statement. The photo attributes which were passed to the function are added to the command parameters collection. Finally, ExecuteScalar function of the command object is invoked and the result is stored in the productPhotoID parameter. If you look closely at the SQL statement, you would notice a insert statement and a select statement. Insert statement would insert the image to the database and the select statement would fetch the productphotoid of the last inserted record.

    private int InsertProductPhoto(string fileName, byte[] imageBytes, byte[] thumbNailImageBytes)
    {                  
    	//fetch the connection string from web.config
        string connString = ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;    
             
        using (SqlConnection conn = new SqlConnection(connString))
        {
            //parameterized insert statement 
            //and select statement to fetch the identity value of the last inserted row
            string sql = @"INSERT INTO [Production].[ProductPhoto]([ThumbNailPhoto]
                            ,[ThumbnailPhotoFileName],[LargePhoto],[LargePhotoFileName]
                            ,[ModifiedDate])
                            VALUES
                            (@ProductThumbNailPhoto
                            ,@ProductPhotoName
                            ,@ProductLargePhoto
                            ,@ProductPhotoName
                            ,GETDATE());
                            SELECT SCOPE_IDENTITY()";
            conn.Open();
            //Initialize a new Command class
            //with the text of the query and a SqlConnection.
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {                    
                //set input parameters values                 
                cmd.Parameters.AddWithValue("@ProductThumbNailPhoto", thumbNailImageBytes);
                cmd.Parameters.AddWithValue("@ProductLargePhoto", imageBytes);
                cmd.Parameters.AddWithValue("@ProductPhotoName", fileName);
    
                //execute the insert statement and fetch the product photo id
                return Convert.ToInt32(cmd.ExecuteScalar());
            }               
        }            
    }
    

    If you look at the last statement of the upload click event handler, we are setting the url of the image control to ProductImageHttpHandler http handler and passing productphotoID returned from InsertProduct method and the imagetype (thumbail or largephoto) in the query string.  In the processrequest method, we fetch ProductPhotoID from the query string. We construct the select query based on the imagetype.   We fetch the photo from the database based on the productPhotoID in the form of byte data using ADO.NET API and we simply write it to the response output stream by invoking BinaryWrite method.

    public class ProductImageHttpHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //get the productid from the query string
            int productPhotoID = Convert.ToInt32(context.Request.QueryString["ProductPhotoID"]);
    
            //get the image from the query string (thumbnail or actual iamge)
            string imageType = Convert.ToString(context.Request.QueryString["ImageType"]);
            if (productPhotoID > 0)
            {
                //fetch the product photo details
                DataTable dtProductPhotoDetails = RetrieveProductImage(productPhotoID, imageType);
    
                //store photo data and file name
                byte[] imageContent = (byte[])dtProductPhotoDetails.Rows[0][0];
                string fileName = dtProductPhotoDetails.Rows[0][1].ToString();
    
                //if the action type is "Download" download the image
                context.Response.BinaryWrite(imageContent);
                context.Response.End();
            }
        }
    
        private DataTable RetrieveProductImage(int ProductPhotoID, string imageType)
        {
            //fetch the connection string from web.config
            string connString = ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
    
            //SQL statement to fetch thumbnail photo
            string sql = @"Select {0},{1} from Production.ProductPhoto PP where ProductPhotoID = {2}";
    
            //if the actiontype is "Download", get the large photo, if not just get the thumbnail photo
            if (string.IsNullOrEmpty(imageType) || imageType == "thumbnail")
            {
                sql = String.Format(sql, "ThumbNailPhoto", "ThumbnailPhotoFileName", ProductPhotoID);
            }
            else
                sql = String.Format(sql, "LargePhoto", "LargePhotoFileName", ProductPhotoID);
    
            DataTable dtProductsPhoto = new DataTable();
            //Open SQL Connection
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();
                //Initialize command object
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
                    SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                    //Fill the result set
                    adapter.Fill(dtProductsPhoto);
                }
            }
            return dtProductsPhoto;
        }
    
        public bool IsReusable
        {
            get{
                return false;
            }
        }
    }
    

    We must now register the handler in Web.config file.  The verb part is just what you want it to respond to (GET, POST, etc.). Path is the file or file extension you want it to respond to and Type is – ClassName, Assembly. The way you register to the handler depends upon the IIS version you are running and its mode (classic or Integrated mode).

    <httpHandlers>	
      <add verb="*" path="*ProductImageHttpHandler.ashx"      type="ASPNETGRIDVIEW_PART2.ProductImageHttpHandler,ASPNETGRIDVIEW_PART2"/>
    </httpHandlers>
    

    Run the application. Enter a name in the file name text field.  We could also derive the filename from the uploaded image, however in this example taking it as an input. Click on the “Browse” button and select an image from the local file system.  I am selecting an IPAD image, I have downloaded from the web.
    resize image and save to database 1

    Click on the “Upload” button and a thumbnail image (generated from actual image) and actual image will be saved to the database and both images are again downloaded from the database and bound to image controls
    resize image and save to database 2

    Be Sociable, Share!
      Post Tagged with , ,

    Written by

    Software architect with over 10 years of proven experience in designing & developing n-tier and web based software applications, for Finance, Telecommunication, Manufacturing, Internet and other Commercial industries. He believes that success depends on one's ability to integrate multiple technologies to solve a simple as well as complicated problem.

    View all articles by

    Email : [email protected]

    2 Responsesso far.

    1. […] If you are interested in resizing the image before saving it to database, take a look at below article. How to resize and save image to database in ASP.NET  […]

    2. kiran says:

      Helped me a lot thankyou very much…….

    Leave a Reply