How to generate dynamic images for your web application

Typically, a web site might show some pictures. These could be pictures of items for sale from a catalog, personal photos, etc. Usually, the web author places these pictures as files in a directory on the web server, and just puts links to them in the authored web pages.

This scheme doesn’t easily allow dynamic pictures.

  • Perhaps the author would like to generate the pictures on the fly, when the web page is being rendered in the remote browser
  • Perhaps the picture is in a database, rather than a file on disk
  • Perhaps the author would like to write some text on the picture, such as a copyright notice.
  • Perhaps dynamically created thumbnails or other sizes are desired (my picture application generates different sized images rotated 90 degrees for my SmartPhone, which has higher vertical than horizontal resolution)
  • It’s a way that you can rotate text, use various fonts, sizes, colors.

We can generate images dynamically to solve these problems.

This sample works in Visual Studio 2005 and Visual Studio 2008: It creates 2 images controls, each with an ImageUrl property specifying to call the default.aspx page with a parameter.

I’ve been using this technique of calling the same page with parameters in ASP for years.

If the parameter is passed:

  • an empty bitmap object is created
  • a graphics object from that image is created
  • some text is drawn and rotated
  • the image is saved to a memory stream
  • the stream is then written back to the browser.

The sample includes code to conditionally choose static images or retrieve images from a table.

This technique can easily be applied to an asp:GridView control to show dynamically generated images in a column of a databound grid.

(For more on the thumbnail table: Create thumbnails of all your digital photos in a single table)

Start Visual Studio

File->New->Web Site.

In the Default.aspx put this text: (or just drag 2 image controls onto the design surface, and set the ImageUrl property)

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="https://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        this is a test<br />

        <asp:Image ID="Image1" ImageUrl="~/Default.aspx?Imageid=one" runat="server" />

        <asp:Image ID="Image2" ImageUrl="~/Default.aspx?Imageid=another" runat="server" /></div>

    </form>

</body>

</html>

In the Default.aspx.vb file (choose View->Code), paste this:

Imports System.Drawing

Partial Class _Default

    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Dim ImageId As String = Request.QueryString("ImageId") ' see if the image is being requested

        If Not ImageId Is Nothing Then

            Dim MyImage As New Bitmap(250, 400) ' create a new blank bitmap

            Dim MyGraphics As Graphics = Graphics.FromImage(MyImage) ' create a Graphics object from the image

            MyGraphics.FillRectangle(Brushes.AliceBlue, MyImage.GetBounds(GraphicsUnit.Pixel)) ' back color

            MyGraphics.RotateTransform(45) ' rotate the contents

            MyGraphics.DrawString(" Test string " + ImageId, New Font("arial", 10, FontStyle.Bold), Brushes.Coral, 0, 0)

            Dim mStream As New IO.MemoryStream ' create a place to write the jpg

            MyImage.Save(mStream, Imaging.ImageFormat.Jpeg)

            Dim Bytes() As Byte = New Byte(mStream.Length - 1) {} ' Byte array to store the jpg

            mStream.Seek(0, IO.SeekOrigin.Begin)

            mStream.Read(Bytes, 0, mStream.Length - 1)

            Response.BinaryWrite(Bytes) ' write the jpg back to the browser

            Return

            ' alternatively, something like this can be used

            If ImageId.Length Mod 2 = 1 Then

                Response.BinaryWrite(System.IO.File.ReadAllBytes(Me.MapPath("~/images/balloon.bmp")))

            Else

                Response.BinaryWrite(System.IO.File.ReadAllBytes(Me.MapPath("~/images/beany.bmp")))

            End If

            Return

            ' or from a Visual Foxpro database:

            Dim oda As New Data.OleDb.OleDbDataAdapter( _

                    "select * from pixthumb where recno()=" + _

                    ImageId.Length.ToString, _

                "provider=vfpoledb.1;data source=d:\pictures\pixthumb.dbf")

            Dim dt As New Data.DataTable

            oda.Fill(dt)

            Dim thumb = dt.Rows(0).Item(1)

            Response.BinaryWrite(thumb)

        End If

    End Sub

End Class

End of code

Now hit F5 to run the code