Saturday, November 6, 2010

Image Handling In ASP.Net

Contents
  • Introduction
  • Store Image
    • In Database
    • In Folder        
  • Display Image in Image Control, GridView and DataList 
    • From Database
    • From Folder
  • Creating Thumbnails
  • Adding Watermark Text on Image
  • Adding Image as Watermark

Introduction

             In this Article  I am going to explain how to handle image in ASP.Net. I seen lot of question regarding "How to save and display image from database in ASP.Net"  in different .net discussing forums. I think it must be helpful for beginners to solve their problems regarding images in ASP.Net.  

Store Images

We can store images in Database and project folders. If it is in Database the datatype of image data is "image" , now we can check the Database design

In Database

here I used create a store procedure to save image in database.


CREATE PROCEDURE [dbo].[sp_UploadImage]
@imageData as image
AS
BEGIN
INSERT INTO Images (imageData) VALUES(@imageData)
END

Now we can look how to save image in Database. we need one FileUpload Control to select file. and need to check file extension to verify uploading file is image or not. below script function "valiadate();"  check the file is image or not, ie we check the file extensions with javascript.

Javascript to check Upload file extension

Now check the .aspx page
 
    
Now server side code. Reading bytes value from FileUpload Control and pass that value with store procedure name in to a HashTable. that hashtable send to DataBaseHelper Class file to save image in Database.
 protected void btnUploadImage_Click(object sender, EventArgs e)
    {
        //server side checking
        if (FileUpload1.PostedFile.ContentType.ToLower().StartsWith("image") && FileUpload1.HasFile)
        {
            Hashtable imageHash = new Hashtable();
            imageHash.Add("@imageData", FileUpload1.FileBytes);
            DataBaseHelper DBHelper = new DataBaseHelper();
            //storing image in to DataBase
            DBHelper.ExecuteNonQuery("sp_UploadImage", imageHash);
        }
    } 
Database with image data
In Folder Saving folder is simple to compare saving in Database. FileUpload control have SaveAs() method to save file. here I save images in "savedImages" folder. We are not keeping any values in database. At the time of display image we pick images from folder using DirectoryInfo and FileInfo Class or Directory.GetFiles Methord
protected void btnUploadToFolder_Click(object sender, EventArgs e)
    {
        //save file in folder
        if (FileUpload1.PostedFile.ContentType.ToLower().StartsWith("image") && FileUpload1.HasFile)
        {
            string savelocation = Server.MapPath("savedImages/");
            string fileExtention = System.IO.Path.GetExtension(FileUpload1.FileName);
            //creating filename to avoid file name conflicts.
            string fileName = Guid.NewGuid().ToString();
            //saving file in savedImage folder.
            string savePath = savelocation + fileName + fileExtention;
            FileUpload1.SaveAs(savePath);
        }
    }
Preview of saved images in folder
Display Images in Image Control, GridView and DataList To display image from Database is not simple as displaying from folders. because we previously saved image as byte in Database. From Database To display image, we need to change  byte data to Image, to convert byte data to image we need to use a separate page, here I am using a Generic Handler page to show image from Database.  In that Generic Handler page we take image byte from Database and render in that Handler page and set image controls src or ImageUrl to that Generic Handler page for example it work like this
//from database
Image1.ImageUrl="Handler.aspx?id=1";
//from folder
Image1.ImageUrl="savedImages/ca34fa6c-8321-492c-938b-5413781bdcde.png";
Display image in Generic Handler page Method 1
  
   public void ProcessRequest (HttpContext context) {
        HttpRequest request = context.Request;
        if (!string.IsNullOrEmpty(request.QueryString["id"]))
        {
            //this hash table contain the SP parameter
            Hashtable hash = new Hashtable();
            hash.Add("@imageID", request.QueryString["id"]);
            DataBaseHelper DBHelper = new DataBaseHelper();

            //DBHelper.SQLExecuteNonQuery(procedure_name,command_parameters) return the object data.
            // casting return value to byte[]
            byte[] imageByte = (byte[])DBHelper.SQLExecuteNonQuery("sp_getImage", hash);
            //creating object of image
            System.Drawing.Image b;
            //creating object of bitmap
            Bitmap bitMap = null;
            //checking byte[] 
            if (imageByte != null && imageByte.Length > 0)
            {
                //creating memoryStream object
                using (MemoryStream mm = new MemoryStream())
                {
                    //wrting to memoryStream
                    mm.Write(imageByte, 0, imageByte.Length);
                    b = System.Drawing.Image.FromStream(mm);
                    bitMap = new System.Drawing.Bitmap(b, b.Width, b.Height);
                    //creating graphic object, to produce High Quality images.
                    using (Graphics g = Graphics.FromImage(bitMap))
                    {
                        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;
                        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        g.DrawImage(bitMap, 0, 0, b.Width, b.Height);
                        g.Dispose(); b.Dispose(); mm.Dispose();
                        //changing content type of handler page
                        context.Response.ContentType = "image/jpeg";
                        //saving bitmap image
                        bitMap.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                        bitMap.Dispose();
                    }
                }
            }
        }
    }
  
Method 2 You can also use this code to render image in Handler page
public void ProcessRequest (HttpContext context) {
        HttpRequest request = context.Request;
        if (!string.IsNullOrEmpty(request.QueryString["id"]))
        {
            //this hash table contain the SP parameter
            Hashtable hash = new Hashtable();
            hash.Add("@imageID", request.QueryString["id"]);
            DataBaseHelper DBHelper = new DataBaseHelper();

            //DBHelper.SQLExecuteNonQuery(procedure_name,command_parameters) return the object data.
            // casting return value to byte[]
            byte[] imageByte = (byte[])DBHelper.SQLExecuteNonQuery("sp_getImage", hash);
            //checking byte[] 
            if (imageByte != null && imageByte.Length > 0)
            {
                context.Response.ContentType = "image/jpeg";
                context.Response.BinaryWrite(imageByte);
            }
        }
    } 
Example of Handler page displaying image, and check the URL, it display 3rd  image from the Database.
Store procedure used to get Image
CREATE PROCEDURE sp_getImage
@imageID as numeric
AS
BEGIN
SELECT imageData FROM Images WHERE imageId=@imageID
END 
I already said how to display image in Image Conrtol. now we can check how to display in GridView Control form folders and Database. From Database In the aspx page I put a GridView and , then set SqlDataSource, after that I  add a Template column, then drag and drop a Image control in Template column  and set ImageUrl of the image control using Image DataBinding Setting image url 
  Source of GridView Passing imageId to Handler.ashx page. It will display image as I said above.
Preview with HTML Source.
Displaying Image From Folder you need to add a template column in GridView after that put one image control on template column, then set image controls DataImageUrlField from DataTable.
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="false">
     <Columns>
         <asp:ImageField  DataImageUrlField="Image">
         </asp:ImageField>
     </Columns>
 </asp:GridView>
Server side code
 private void BindImage()
    {
     
        DataTable dt = new DataTable();
        dt.Columns.Add(new DataColumn("Image", typeof(string)));
        DataRow dr;
        int i = 0;
  //fetching files from savedImages folder
        foreach (string file in Directory.GetFiles(Server.MapPath(@"savedImages\")))
        {
            dr = dt.NewRow();
            dt.Rows.Add(dr);
            dr["Image"] = "savedImages/" + System.IO.Path.GetFileName(file);
            i += 1;
        }
        GridView2.DataSource = dt;
        GridView2.DataBind();
    }
Now we can check how DataList works. Datalist is more simple control than GridView. Here aslo we call Database image with Generic Handler file Handler.ashx and pass "id" as QueryString. handler file display image, and we point that image in to our DataList Control.
<asp:DataList ID="DataList1" runat="server"
            RepeatColumns="3" RepeatDirection="Horizontal">
            <ItemTemplate>
                <table>
                    <tr>
                        <td valign="middle" align="center" style="background-color:#cccccc;border:1px solid gray;width:150px;height:150px;"><%#DataBinder.Eval(Container.DataItem, "images") %></td>
                    </tr>
                </table>
            </ItemTemplate>
        </asp:DataList>
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            BindDataList();
    }
    private void BindDataList()
    {
        string sqlCmd = "SELECT imageid FROM Images";
        DataBaseHelper DBHelper = new DataBaseHelper();
        DataTable dt = DBHelper.GetTable(sqlCmd);
        //adding new column to disply image
        DataColumn imageCol = new DataColumn("images", typeof(string));
        dt.Columns.Add(imageCol);
        
        if (dt.Rows.Count > 0)
        {
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                dt.Rows[i][imageCol] = string.Format("<img src='Handler.ashx?id={0}' alt='' style='width:100px' />", dt.Rows[i][0].ToString());
            }
        }
        DataList1.DataSource = dt;
        DataList1.DataBind();
    }
Preview of Images in DataList Control
Creating Thumbnails image To create a thumbnail we need a image. we can pick image from FileUpload Control, then we need to know dimension of image ie [ Width x Height ]. Here I create a UI to handle this. check the UI
To maintain aspect ratio of image with height and width I use a class AspectRatio.cs you can get the source code "Browse Code" or "Download Source" Section. Now we can look the code of thumbnail creating section. As I said above here I call a function to create thumbs. let look at this. Below method returns Bitmap image, I am saving that image in root folder.
 public Bitmap CreateThumbnail(byte[] imageByte, bool maintainAspectRatio, int desiredWidth, int desiredHeight)
    {
        Bitmap bmp = null;
        try
        {
            MemoryStream memStream = new MemoryStream(imageByte);
            System.Drawing.Image img = System.Drawing.Image.FromStream(memStream);

            if (maintainAspectRatio)
            {
                AspectRatio aspectRatio = new AspectRatio();
                aspectRatio.WidthAndHeight(img.Width, img.Height, desiredWidth, desiredHeight);
                bmp = new Bitmap(img, aspectRatio.Width, aspectRatio.Height);
            }
            else
            {
                bmp = new Bitmap(img, desiredWidth, desiredHeight);
            }
            memStream.Dispose();
        }
        catch(Exception ex)
        {
            havException = true;
            ExceptionMessage = ex.Message;
        }
        return bmp;
    }

Server side code of "Create Thumbnail" Button. You can see this button in above image. here I pass image byte[] to CreateThumbnail Method. it return Bitmap Image. and save that file in root folder.
 protected void btnCreateThumb_Click(object sender, EventArgs e)
    {
        int width = 0;
        int height = 0;
        byte[] image = FileUpload1.FileBytes;
        Int32.TryParse(txtDWidth.Text, out width);
        Int32.TryParse(txtDHeight.Text, out height);
        ImageHandler imageHandler = new ImageHandler();
        bool maintainAR = cbxAspectRation.Checked;
        //calling CreateThumbnail Method to create thumb images
        //it returns Bitmap Image. 
        Bitmap bmp = imageHandler.CreateThumbnail(image, maintainAR, width, height);
        if (bmp != null)
        {
            //creating a file name with guid.
            string fileName = Guid.NewGuid().ToString() + ".jpg";
            //saving in current root folder.
            bmp.Save(Server.MapPath(fileName));
            //set image controls ImageUrl to saved Image, this is to view the thumbnail image
            Image1.ImageUrl = fileName;
        }
        else
        {
            //exception part
            if (imageHandler.havException)
            {
                Response.Write(imageHandler.ExceptionMessage);
            }
        }
    }
You can check preview of Thumbnail ,Height and Width of image with the help of Firebug  console.
Creating Watermark Text on Image Now we can discuss how to add Watermark on image. I think you know about Watermark. here I call a method AddWatermarkText to add watermark on image. I pass image byte and watermark text to this method. method create on System.Drawing.Image object from MemoryStream. MemoryStream Hold the image Byte. using System.Drawing.SolidBrush and System.Drawing.Font we create Text after that
 
Graphics.DrawString(string s, Font font, Brush brush, PointF point);
we write text on Image. below method is AddWatermarkText(byte[] imageByte,string textOnImage); you can check that.
 

public Image AddWatermarkText(byte[] imageByte,string textOnImage)
    {
        System.Drawing.Image img = null;
        try
        {
            MemoryStream memStream = new MemoryStream(imageByte);
            img = System.Drawing.Image.FromStream(memStream);
            Graphics g = System.Drawing.Graphics.FromImage(img);
            Font font = new Font("Aril", 30, FontStyle.Bold);

            SolidBrush solidBrush = new SolidBrush(Color.Red);
            Point point = new Point(img.Width / 3, img.Height / 2);
            g.DrawString(textOnImage, font, solidBrush, point);
            g.Save();

            memStream.Dispose();
            g.Dispose();
            solidBrush.Dispose();
            font.Dispose();
        }
        catch(Exception ex)
        {
            havException = true;
            ExceptionMessage = ex.Message;
        }
        return img;
    }
above method return Image. I am saving this image in root folder and display it using a Image control. you can check the UI of add Watermark Page and watermark on resultant Image.
Now we can check the code of Add Watermark button
 protected void btnAddWaterMark_Click(object sender, EventArgs e)
    {
        if (FileUpload1.HasFile)
        {
            byte[] imgbyte = FileUpload1.FileBytes;
            //creating object of ImageHandler Class
            ImageHandler imageHandler = new ImageHandler();
            System.Drawing.Image imageWithWatermark = imageHandler.AddWatermarkText(imgbyte, txtWaterMarkText.Text);
            if (imageWithWatermark != null)
            {
                //file name to save
                string saveFileName = Guid.NewGuid().ToString() + ".jpg";
                //saving image in current root location
                imageWithWatermark.Save(Server.MapPath(saveFileName));
                //displaying image file in a Image Control
                Image1.ImageUrl = saveFileName;
                imageWithWatermark.Dispose();
            }
            else
            {
                if (imageHandler.havException)
                {
                    Response.Write(imageHandler.ExceptionMessage);
                }
            }
        }
    }
Image as Watermark In this section I am explaining how to add Image as watermark. I think you seen same website with images. they have their log on image. we can check how to do something link that first we need a logo image here I take codeproject's logo image to explain this example. I save CP logo image in watermarklogo folder.
I am embedding CP logo image in to an upload image, using Graphics.DrawImage(Image image, Point point); Method. here I add add fading to logo image using TextureBrush
 //add fading to logo image  using TextureBrush
        System.Drawing.Image waterMarkimage = System.Drawing.Image.FromFile(Server.MapPath("watermarklogo/CodeprojectLogo.jpg"));
        Graphics opacity = System.Drawing.Graphics.FromImage(waterMarkimage);
        Rectangle imageRect = new Rectangle(0, 0, waterMarkimage.Width, waterMarkimage.Height);
        Brush brush = new TextureBrush(waterMarkimage, imageRect);
        opacity.FillRectangle(brush, imageRect);
        opacity.Save();
check the sample image
Check the source code
protected void btnAddImageAsWaterMark_Click(object sender, EventArgs e)
    {
        byte[] imageByte = FileUpload1.FileBytes;
        MemoryStream memStream = new MemoryStream(imageByte);
        System.Drawing.Image img = System.Drawing.Image.FromStream(memStream);

        //add fading to logo image  using TextureBrush
        System.Drawing.Image waterMarkimage = System.Drawing.Image.FromFile(Server.MapPath("watermarklogo/CodeprojectLogo.jpg"));
        Graphics opacity = System.Drawing.Graphics.FromImage(waterMarkimage);
        Rectangle imageRect = new Rectangle(0, 0, waterMarkimage.Width, waterMarkimage.Height);
        Brush brush = new TextureBrush(waterMarkimage, imageRect);
        opacity.FillRectangle(brush, imageRect);
        opacity.Save();
       
        Graphics g = System.Drawing.Graphics.FromImage(img);
        Point point = new Point(img.Width / 3, img.Height / 2);
        g.DrawImage(waterMarkimage, point);
        string filename = Guid.NewGuid().ToString() + ".jpg";
        img.Save(Server.MapPath(filename));
        
        opacity.Dispose();
        memStream.Dispose();
        g.Dispose();
        waterMarkimage.Dispose();
        img.Dispose();

        Image1.ImageUrl = filename;
    } 
Download full source code

9 comments:

Nisar said...

i just want to say one word
Superb!!!!

guru330 said...

How to update or modify already uploaded images and I want say that how to direct display images using folder and display in image control without using grid view control.

Reply

Raju.M said...

1: How to update or modify already uploaded images??

Keep the ID and Update the image, I mean the Byte[] if image in DB otherwise you can change in image location where you saved in DB

Show images in Folder. here I used one image control.
Image1.ImageUrl=yourfolder/imagefile

chitti said...

I have stored image with PATH,then how to retrieve image from database and resize it, and attach to the control......

I am able to get till resizing the image but i am unable to attach that to user conrol... how to do that........

here is my code behind

protected void Page_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt = CommonVars.objService.GetImages();
string img = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
img = dt.Rows[i][1].ToString();

dt.Rows[i][1] = @"~/GAVS.EMO.WebApp/" + dt.Rows[i][1].ToString();

}
DataList1.DataSource = dt;
DataList1.DataBind();

string _path = Server.MapPath(@"~\" + img);
Bitmap upBmp = (Bitmap)Bitmap.FromFile(_path);
Int32 upWidth = upBmp.Width;
Int32 upHeight = upBmp.Height;
int thumbHeight,thumbWidth = 132;;



if (upHeight > upWidth)
{
thumbHeight = (upHeight / upWidth) * thumbWidth;
}
else
thumbHeight = (upWidth / upHeight) * thumbWidth;

System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(upWidth,(int)upHeight);
System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(bitmap);
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

System.Drawing.Rectangle rectDestination = new System.Drawing.Rectangle(0, 0, upWidth, upHeight);
gr.DrawImage(upBmp, rectDestination, 0, 0, upWidth, upHeight, GraphicsUnit.Pixel);

//bitmap.Save(Response.OutputStream, ImageFormat.Jpeg);
}

plz help me....

Raju.M said...

Hi chitti,
Use a separate page to render images. In above article I used a Handler page.

you want to do like this.

image1.imageUrl="yourImageRenderPage.aspx?imageid=databasefileId";

In yourImageRenderPage
take location from database with respect Query string ID

then
Bmp=bitmap.fromFile(location);
//resize
//bitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

jyothi said...

Thanks for ur reply...
I want to display the image along with my master page,I am unable to do that
since the below will display in separate page...
bitmap.Save(Response.OutputStream, ImageFormat.Jpeg);
how to attach bitmap to user control???
Dynamically i need to build this photo gallery,since I dont know how many images i will get..

thanks in advance....

Arun Kakkar said...

Thanks buddy
Its a EXCELLENT WAY to explain with full examples, pictures etc
I hope we got many more such important topics from you.
Again Thank you very much

Arun Kakkar said...

I have one problem which might not be mentioned in this blog
I have an application of AddressBook
I can save address with picture & display back in image control from database,
but I want to save the edited record in database where image is stored in image control.
In your blog, you save images from fileupload control, its ok, but i want to save images which were displayed in image control from database using http handler like .ashx you used in this blog.
Please give me the solutions if you have any.
Waiting for positive reply
Thanking you in advance.
arunkakkar1@gmail.com

Anonymous said...

vary helpful this artical
but sir i want to image save in 64 bit in folder in asp.net C#.
thanks