12.4. Displaying Thumbnail Images

Problem

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

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.

Display thumbnails output

Figure 12-4. Display thumbnails output

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.

Tip

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.

Warning

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.

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
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset