Recipe 12.4 Displaying Thumbnail Images

     

12.4.1 Problem

You want to be able to display a page of images stored in your database in thumbnail format.

12.4.2 Solution

Implement the first of the two ASP.NET pages described in Recipe 12.3, changing the Page_Load method in the code-behind class to scale the full- sized image retrieved from the database to the appropriate size for a thumbnail presentation.

In the Page_Load method of the code-behind class for the page, use the .NET language of your choice to:

  1. Create a System.Drawing.Image object from the byte array retrieved from the database.

  2. Use a constant to define the height of the thumbnail and then calculate the width to maintain the aspect ratio of the image.

  3. Use the GetThumbnailImage method of the Image object to scale the image to the desired size.

  4. Load the thumbnail image into a MemoryStream and then write it to the Response object.

Example 12-16 and Example 12-17 show the VB and C# code-behind class for our example that illustrates this solution. (See the CH12ImageFromDatabaseVB .aspx file and VB and C# code-behind files in Recipe 12.3 for our starting point.)

To display the thumbnails, create another ASP.NET page, add a DataList control with image tags in the ItemTemplate , and then use data binding to set the src attributes of the image tags.

In the .aspx file for the page:

  1. Use a DataList control to provide the ability to generate a list using data binding.

  2. Use a HeaderTemplate to label the table of images.

  3. Use an ItemTemplate to define an image that is displayed in the DataList .

In the code-behind class for the page, use the .NET language of your choice to:

  1. Open a connection to the database.

  2. Build a query string, and read the list of images from the database.

  3. Assign the data source to the DataList control and bind it.

  4. Set the src attribute of the image tags used to display the thumbnail images in the ItemDataBound event of the DataList .

Example 12-18 through Example 12-20 show the .aspx file and VB and C# code-behind files for the application that uses the dynamically generated images. The output produced by the page is shown in Figure 12-4.

Figure 12-4. Display thumbnails output
figs/ancb_1204.gif

12.4.3 Discussion

The rationale for this recipe is similar to that of Recipe 12.3. That is, you need a convenient way to display images from a database, in this case a page of thumbnail images, and it must efficiently move the image data to the browser while maintaining the maximum flexibility in selecting images from the data store.

This recipe uses the same approach as in Recipe 12.3 where, with one page, an image is retrieved from the database and streamed to the browser, and a second page is used to generate the image requests and display the results, which in this case is a set of thumbnails. Additionally, the image retrieval page must scale the images to thumbnail size.

In our example that demonstrates the solution, the Page_Load method of the code-behind for the image building page (the CH12ThumbnailFromDatabase page) is modified to scale the full-sized image retrieved from the database to the appropriate size for a thumbnail presentation.

The first step to scale the image is to create a System.Drawing.Image object from the byte array retrieved from the database. This requires loading the byte array into a MemoryStream and then using the FromStream method of the Image class to create the image.

Next, we need to calculate how much to reduce the image. A constant is used to define the height of the thumbnail, and the width is calculated by determining how much the height is being reduced and multiplying the value times the width of the full-size image.

It is important to reduce the height and width by the same scale factor to keep the aspect ratio correct. If the height or width is reduced by a different amount, the image will be distorted .


Handling mixed calculations of integers and doubles can result in unexpected results. Visual Basic is more tolerant and will allow the division of two integers with the quotient set to a variable of type double and result in the correct value. C# will return an integer result from the division of two integers, effectively truncating the result. It is best to cast at least the numerator to the type of the resultant variable.


Now that the width and height of the thumbnail are determined, the GetThumbnailImage method of the full-size image can be used to return a scaled-down image to use as the thumbnail.

Once the thumbnail image is created it can be loaded into a MemoryStream and then written to the Response object in the same manner described in Recipe 12.1.

The web form used to display the thumbnails uses a DataList control to provide the ability to generate the list using data binding. The DataList is configured to display four columns horizontally by setting the RepeatColumns attribute to " 4 " and the RepeatDirection attribute to " Horizontal ". This will start a new row in the table used to display the images after every fourth image.

A HeaderTemplate is used to label the table of images. The template can contain any HTML that can be properly displayed in a table. In this example, the template consists of a single table row containing a single cell with the heading for the table. The colspan attribute is set to " 4 " to cause the cell to span across all columns in the table, and the align attribute is set to " center " to center the heading.

An ItemTemplate is used to define an item that is displayed in the DataList . In this example, the template consists of an img tag that simply has the ID and Runat attributes set to provide access to the item from the code-behind.

The Page_Load method in the code-behind reads the list of images from the database and binds them to the DataList control. This is accomplished by opening a connection to the database, querying for a list of the image IDs, then setting the DataSource and calling the dataBind method of the DataList . The only data we need from the database is the list of IDs for the images. These will be used to set the image sources, and the actual reading of the image data will be done by the code described earlier.

The src attribute of the image tags used to display the thumbnail images is set in the ItemDataBound event of the DataList . The ItemDataBound event is called for every item in the DataList , including the header. Therefore, it is important to check the item type, since image tags only appear in the data items. Data items can be an Item or an AlternatingItem .

If the item is actually a data item, we need to get a reference to the image control in the item. This is accomplished by using the FindControl method of the item to locate the image control using the ID assigned in the .aspx file. This reference must be cast to an HtmlImage type since the return type of FindControl is an Object .

Once a reference to the image is obtained, the src attribute can be set to the name of the ASP.NET page that is used to generate the thumbnail image passing the ID of the image in the URL. As with Recipe 12.3, constants are used for the name of the page and the name of the item passed in the URL.

The ID of the image is obtained from the DataItem method of the item. This must be cast to a DbDataRecord type to allow "looking up" the ID of the image using the name of the column included in the SQL query used in the bindData method described earlier.

This example presents a useful method of displaying thumbnails of images stored in a database. When used with reasonably small images, the performance is acceptable for most applications. If the images are very large, however, you may want to create the thumbnail images offline and store them in the database to avoid the performance hit for real-time conversion.

12.4.4 See Also

Recipe 12.1; Recipe 12.3

Example 12-16. Page_Load method for generating thumbnail image (.vb)
 Private Sub Page_Load(ByVal sender As System.Object, _                         ByVal e As System.EventArgs) Handles MyBase.Load  'height of the thumbnail created from the original image   Const THUMBNAIL_HEIGHT As Integer = 75  Dim dbConn As OleDbConnection     Dim dc As OleDbCommand     Dim imageData( ) As Byte     Dim strConnection As String     Dim strSQL As String     Dim ms As MemoryStream     Dim fullsizeImage As image     Dim thumbnailImage As image     Dim thumbnailWidth As Integer     Dim imageID As String     If (Not Page.IsPostBack) Then       Try         'get the ID of the image to retrieve from the database         imageID = Request.QueryString(QS_IMAGE_ID)         'get the connection string from web.config and open a connection          'to the database         strConnection = _             ConfigurationSettings.AppSettings("dbConnectionString")         dbConn = New OleDb.OleDbConnection(strConnection)         dbConn.Open( )         'build the query string and get the data from the database         strSQL = "SELECT ImageData " & _                  "FROM BookImage " & _                  "WHERE BookImageID=" & imageID         dc = New OleDbCommand(strSQL, dbConn)         imageData = CType(dc.ExecuteScalar( ), Byte( ))  'create an image from the byte array   ms = New MemoryStream(imageData)   fullsizeImage = System.Drawing.Image.FromStream(ms)   'calculate the amount to shink the height and width   thumbnailWidth = _   CInt(Math.Round((CDbl(THUMBNAIL_HEIGHT) / _   fullsizeImage.Height) * fullsizeImage.Width))   'create the thumbnail image   thumbnailImage = fullsizeImage.GetThumbnailImage(thumbnailWidth, _   THUMBNAIL_HEIGHT, _   Nothing, _   IntPtr.Zero)   'write thumbnail to the response object   ms = New MemoryStream   thumbnailImage.Save(ms, ImageFormat.Jpeg)   Response.ContentType = "image/jpg"   Response.BinaryWrite(ms.ToArray( ))  Finally         'clean up         If (Not IsNothing(dbConn)) Then           dbConn.Close( )         End If       End Try     End If   End Sub  'Page_Load 

Example 12-17. getImage method for generating thumbnail image (.cs)
 private void Page_Load(object sender, System.EventArgs e)   {  // height of the thumbnail created from the original image   const int THUMBNAIL_HEIGHT = 75;  OleDbConnection dbConn = null;     OleDbCommand dc = null;     byte[] imageData = null;     String strConnection = null;     String strSQL = null;     MemoryStream ms = null;     System.Drawing.Image fullsizeImage  = null;     System.Drawing.Image thumbnailImage  = null;     int thumbnailWidth;     String imageID = null;     if (!Page.IsPostBack)     {       try       {         // get the ID of the image to retrieve from the database         imageID = Request.QueryString[QS_IMAGE_ID];         // get the connection string from web.config and open a connection          // to the database         strConnection =            ConfigurationSettings.AppSettings["dbConnectionString"];         dbConn = new OleDbConnection(strConnection);         dbConn.Open( );         // build the query string and get the data from the database         strSQL = "SELECT ImageData " +                  "FROM BookImage " +                  "WHERE BookImageID=" + imageID;         dc = new OleDbCommand(strSQL, dbConn);         imageData = (byte[])(dc.ExecuteScalar( ));  // create an image from the byte array   ms = new MemoryStream(imageData);   fullsizeImage = System.Drawing.Image.FromStream(ms);   // calculate the amount to shink the height and width   thumbnailWidth =   Convert.ToInt32(Math.Round((Convert.ToDouble(THUMBNAIL_HEIGHT) /   fullsizeImage.Height) * fullsizeImage.Width));   // create the thumbnail image   thumbnailImage = fullsizeImage.GetThumbnailImage(thumbnailWidth,   THUMBNAIL_HEIGHT,   null,   IntPtr.Zero);   // write thumbnail to the response object   ms = new MemoryStream( );   thumbnailImage.Save(ms, ImageFormat.Jpeg);   Response.ContentType = "image/jpg";   Response.BinaryWrite(ms.ToArray( ));  }       finally       {         if (dbConn != null)         {           dbConn.Close( );         }       }     }   }  // Page_Load 

Example 12-18. Display thumbnail images (.aspx)
 <%@ Page Language="vb" AutoEventWireup="false"           Codebehind="CH12TestThumbnailsFromDatabaseVB.aspx.vb"           Inherits="ASPNetCookbook.VBExamples.CH12TestThumbnailsFromDatabaseVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html>   <head>     <title>Display Thumbnails</title>     <link rel="stylesheet" href="css/ASPNetCookbook.css">   </head>   <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0">     <form id="frmDisplayThumbnails" method="post" runat="server">       <table width="100%" cellpadding="0" cellspacing="0" border="0">         <tr>           <td align="center">             <img src="images/ASPNETCookbookHeading_blue.gif">           </td>         </tr>         <tr>           <td class="dividerLine">             <img src="images/spacer.gif" height="6" border="0"></td>         </tr>       </table>       <table width="90%" align="center" border="0">         <tr>           <td align="center">&nbsp;</td>         </tr>         <tr>           <td align="center" class="PageHeading">             Display Thumbnail Images (VB)           </td>         </tr>         <tr>           <td><img src="images/spacer.gif" height="10" border="0"></td>         </tr>         <tr>           <td align="center">  <asp:DataList ID="dlImages" Runat="server"   RepeatColumns="4" RepeatDirection="Horizontal"   RepeatLayout="Table" Width="50%">   <HeaderTemplate>   <tr>   <td colspan="4" class="SubHeading" align="center">   Thumbnails of Images In Database<br /><br />   </td>   </tr>   </HeaderTemplate>   <ItemTemplate>   <img id="imgThumbnail" runat="server" border="0" >   </ItemTemplate>   </asp:DataList>  </td>         </tr>       </table>     </form>   </body> </html> 

Example 12-19. Display thumbnail images code-behind (.vb)
 Option Explicit On  Option Strict On '----------------------------------------------------------------------------- ' '   Module Name: CH12TestThumbnailsFromDatabaseVB.aspx.vb ' '   Description: This module provides the code behind for the  '                CH12TestThumbnailsFromDatabaseVB.aspx page. ' '***************************************************************************** Imports Microsoft.VisualBasic Imports System Imports System.Configuration Imports System.Data Imports System.Data.Common Imports System.Data.OleDb Imports System.Web.UI.WebControls Namespace ASPNetCookbook.VBExamples   Public Class CH12TestThumbnailsFromDatabaseVB     Inherits System.Web.UI.Page     'controls on the form     Protected WithEvents dlImages As System.Web.UI.WebControls.DataList     '***************************************************************************     '     '   ROUTINE: Page_Load     '     '   DESCRIPTION: This routine provides the event handler for the page load     '                event.  It is responsible for initializing the controls     '                on the page.     '     '---------------------------------------------------------------------------     Private Sub Page_Load(ByVal sender As System.Object, _                           ByVal e As System.EventArgs) Handles MyBase.Load       Dim dbConn As OleDbConnection       Dim dc As OleDbCommand       Dim dr As OleDbDataReader       Dim strConnection As String       Dim strSQL As String       If (Not Page.IsPostBack) Then         Try  'get the connection string from web.config and open a connection   'to the database   strConnection = _   ConfigurationSettings.AppSettings("dbConnectionString")   dbConn = New OleDb.OleDbConnection(strConnection)   dbConn.Open( )   'build the query string and get the data from the database   strSQL = "SELECT BookImageID " & _   "FROM BookImage"   dc = New OleDbCommand(strSQL, dbConn)   dr = dc.ExecuteReader( )   'set the source of the data for the repeater control and bind it   dlImages.DataSource = dr   dlImages.DataBind( )  Finally           'clean up           If (Not IsNothing(dbConn)) Then             dbConn.Close( )           End If         End Try       End If     End Sub  'Page_Load     '***************************************************************************     '     '   ROUTINE: dlImages_ItemDataBound     '     '   DESCRIPTION: This routine is the event handler that is called for each      '                item in the datalist after a data bind occurs.  It is      '                responsible for setting the source of the image tag to     '                the URL of the page that will generate the thumbnail     '                images with the ID of the appropriate image for the item.     '---------------------------------------------------------------------------  Private Sub dlImages_ItemDataBound(ByVal sender As Object, _   ByVal e As System.Web.UI.WebControls.DataListItemEventArgs) _   Handles dlImages.ItemDataBound   Dim img As System.Web.UI.HtmlControls.HtmlImage   'make sure this is an item in the data list (not header etc.)   If ((e.Item.ItemType = ListItemType.Item) Or _   (e.Item.ItemType = ListItemType.AlternatingItem)) Then   'get a reference to the image used for the bar in the row   img = CType(e.Item.FindControl("imgThumbnail"), _   System.Web.UI.HtmlControls.HtmlImage)   'set the source to the page that generates the thumbnail image   img.Src = CH12ThumbnailFromDatabaseVB.PAGE_NAME & "?" & _   CH12ThumbnailFromDatabaseVB.QS_IMAGE_ID & "=" & _   CStr(CType(e.Item.DataItem, DbDataRecord)("BookImageID"))   End If   End Sub  'dlImages_ItemDataBound  End Class  'CH12TestThumbnailsFromDatabaseVB End Namespace 

Example 12-20. Display thumbnail images code-behind (.cs)
 //---------------------------------------------------------------------------- // //   Module Name: CH12TestThumbnailsFromDatabaseCS.aspx.cs // //   Description: This module provides the code behind for the  //                CH12TestThumbnailsFromDatabaseCS.aspx page // //**************************************************************************** using System; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.OleDb; using System.Web.UI.WebControls; namespace ASPNetCookbook.CSExamples {   public class CH12TestThumbnailsFromDatabaseCS : System.Web.UI.Page   {     // controls on the form     protected System.Web.UI.WebControls.DataList dlImages;                                             //************************************************************************     //     //   ROUTINE: Page_Load     //     //   DESCRIPTION: This routine provides the event handler for the page      //                load event.  It is responsible for initializing the      //                controls on the page.     //------------------------------------------------------------------------     private void Page_Load(object sender, System.EventArgs e)     {       OleDbConnection dbConn = null;       OleDbCommand dc = null;       OleDbDataReader dr = null;       String strConnection = null;       String strSQL = null;       // wire the item data bound event       this.dlImages.ItemDataBound +=          new DataListItemEventHandler(this.dlImages_ItemDataBound);       if (!Page.IsPostBack)       {         try         {  // get the connection string from web.config and open a connection   // to the database   strConnection =   ConfigurationSettings.AppSettings["dbConnectionString"];   dbConn = new OleDbConnection(strConnection);   dbConn.Open( );   // build the query string and get the data from the database   strSQL = "SELECT BookImageID " +   "FROM BookImage";   dc = new OleDbCommand(strSQL, dbConn);   dr = dc.ExecuteReader( );   // set the source of the data for the repeater control and bind it   dlImages.DataSource = dr;   dlImages.DataBind( );  }         finally         {           // clean up           if (dbConn != null)           {             dbConn.Close( );           }         }       }     }  // Page_Load     //************************************************************************     //     //   ROUTINE: dlImages_ItemDataBound     //     //   DESCRIPTION: This routine is the event handler that is called for       //                each item in the datalist after a data bind occurs.        //                It is responsible for setting the source of the image      //                tag to the URL of the page that will generate the      //                thumbnail images with the ID of the appropriate image      //                for the item.     //------------------------------------------------------------------------  private void dlImages_ItemDataBound(Object sender,   System.Web.UI.WebControls.DataListItemEventArgs e)   {   System.Web.UI.HtmlControls.HtmlImage img = null;   // make sure this is an item in the data list (not header etc.)   if ((e.Item.ItemType == ListItemType.Item)   (e.Item.ItemType == ListItemType.AlternatingItem))   {   // get a reference to the image used for the bar in the row   img = (System.Web.UI.HtmlControls.HtmlImage)   (e.Item.FindControl("imgThumbnail"));   // set the source to the page that generates the thumbnail image   img.Src = CH12ThumbnailFromDatabaseCS.PAGE_NAME + "?" +   CH12ThumbnailFromDatabaseCS.QS_IMAGE_ID + "=" +   (((DbDataRecord)(e.Item.DataItem))["BookImageID"]).ToString( );   }   }  // dlImages_ItemDataBound  }  // CH12TestThumbnailsFromDatabaseCS } 



ASP. NET Cookbook
ASP.Net 2.0 Cookbook (Cookbooks (OReilly))
ISBN: 0596100647
EAN: 2147483647
Year: 2006
Pages: 179

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net