Dynamically creating an image in Cold Fusion using csImageFile

This page explains how to stream an image to the browser when it is generated from a Cold Fusion script using our csImageFile component. In earlier versions of Cold Fusion, such as version 5, the image could not be sent directly from csImageFile and it had to be saved in a temporary file first, and then streamed using the <cfcontent> tag. There can be complications with passing variables through the application and with debugging and we will address these issues in the next two pages.

In later versions of Cold Fusion, with J2EE support, it became possible to stream a file using the PageContext Object. This technique is described later on this page.

In an ordinary web page that displays some text and a single image, there are two files present.

  1. The HTML file, which contains formatted text and an <img> tag to specify where the image goes and the URL of that image. In a Cold Fusion application this page may have a .cfm extension but its output is text/html.
  2. The image, which may be a .gif, .jpg, .png, or possibly a .bmp.

The address in the browser is that of the HTML page and the browser will automatically request the image as it loads the page and finds the <img> tag.

If we replace the static image file with a dynamically generated image we must replace the URL in the <img> tag with that of the script that produces the image. For example, if we have a web page containing some text and a dynamically generated image, the web page could have the following HTML code:

<body>
<p>Some text above the image</p>
<img src="image.cfm">
<p>Some text below the image</p>
</body>

The script "image.cfm" uses csImageFile to create an image and it sends a binary data stream preceded with an appropriate MIME type specification so that the browser will treat it as an image. The code for "image.cfm" could be one of the following.

Streaming an image using a temporary file

<cfcache action="flush">
<cfobject action="create" name="Image" class="csImageFile.Manage">
<cfset Image.NewImage(200, 200, "FF0000")>
<cfset TempFile = ExpandPath(".") & "\" & CreateUUID() & ".gif">
<cfset Image.WriteFile(#TempFile#)>
<cfcontent type="image/gif" deletefile="yes" file=#TempFile#>

The first line of code prevents the script from being cached. The csImageFile object is created and called "Image". This example uses the full version of the component, the trial would use "csImageFileTrial.Manage". A new image is created which is simply a red square, 200 pixels across. The last three lines create a temporary GIF file and then stream it to the browser using the cfcontent tag.

The temporary file is stored in the same directory as the script, which is found using the ExpandPath function. A unique file name can be generated by using the CreateUUID function. This means that two separate users calling the same script will have different temporary file names. The cfcontent tag sets the MIME type, in this case it is "image/gif" and it automatically deletes the file after use because the deletefile attribute is "yes". The Internet Guest User must have Modify or Full Control permission on the directory or the file will not be deleted.

Streaming an image using the PageContext object

<cfcache action="flush">
<cfobject action="create" name="Image" class="csImageFile.Manage">
<cfscript>
Image.NewImage(200, 200, "FF0000");
Context = GetPageContext();
Context.SetFlushOutput(false);
Response = Context.GetResponse().GetResponse();
Out = Response.GetOutputStream();
Response.SetContentType("image/gif");
Out.Write(Image.GIFData);
Out.Flush();
Response.Reset();
Out.Close();
</cfscript>

For other image types, set the Content Type to the appropriate value, e.g. "image/jpeg" for JPG and "image/png" for PNG.

In both of the above cases it is important to note that there is no text or HTML output in the script. There are no <cfoutput> tags, no HTML tags and there is no attempt to redirect the page after it loads. None of these would be meaningful because the output of the script is a binary data stream containing a single image and nothing else. Any other characters would corrupt the image. In the first case, no more lines of script will execute after the cfcontent line.

If either script contains an error the server will send an HTML page to show the error message. This cannot be interpreted as an image by the browser so the browser will show an empty image marker. This makes debugging difficult but we will explain more later.