cfimage manipulates images directly in CFML, resizing, rotating, adding a border, converting formats, generating a CAPTCHA, or reading an image's own metadata, without reaching for an external image library.
Learning Objectives
After completing this lesson, you'll be able to:
- Resize and rotate an image with cfimage.
- Convert between formats and generate a CAPTCHA image.
- Read an image's metadata before deciding how to process it.
- Recognize real format limitations and a genuine Lucee naming trap.
How cfimage Fits In
Source Image (file / URL / variable)
cfimage action="..."
File, Browser, or Variable Output
A Basic Resize
<cfimage source="../images/photo.jpg" action="resize" width="100" height="100" destination="photo_thumbnail.jpg" overwrite="yes">
cfimage's Attributes
| Attribute | Meaning |
|---|---|
| action | Defaults to read |
| source | File path, URL, or variable to read from (required for most actions) |
| destination | Output file path (required for convert and write) |
| name | Variable to hold the result (required for read) |
| angle | Rotation in degrees (required for rotate) |
| color / thickness | Border color (default black) and pixel width (default 1) |
| height / width | Required for captcha and resize |
| interpolation | Resize algorithm, defaults to highestQuality (also bilinear, bicubic, lanczos, mitchell) |
| quality | JPEG-only, 0–1, defaults to 0.75, for write |
| format | For writeToBrowser: png (default), jpg, jpeg, or webp |
| text / difficulty / fontSize | For captcha: the display text, low/medium/high complexity, and font point size |
| isBase64 | Whether source is a Base64-encoded string (default no) |
| overwrite | Whether to replace an existing destination file (default no) |
The Nine Actions
| action | Does |
|---|---|
| read | Loads an image into memory (the default action) |
| resize | Changes an image's dimensions |
| rotate | Rotates an image by a given angle |
| border | Adds a rectangular border |
| convert | Changes an image's file format |
| captcha | Generates a distorted-text CAPTCHA image |
| info | Retrieves an image's metadata |
| write | Saves the image to a file |
| writeToBrowser | Sends the image directly as the response |
A Real Example: Adding a Border
<cfimage source="../images/photo.jpg" action="border" thickness="5" color="red" destination="photo-bordered.jpg" overwrite="yes">
A Real Example: Generating a CAPTCHA
<cfimage action="captcha" text="#captchaCode#" width="200" height="60" difficulty="medium" name="captchaImage">
A Real Example: Reading Metadata Before Processing
<cfimage source="#uploadedFilePath#" action="info" structName="imageInfo">
<cfif imageInfo.width GT 2000>
<cfimage source="#uploadedFilePath#" action="resize" width="2000" height="" destination="#uploadedFilePath#" overwrite="yes">
</cfif>Checking an uploaded image's actual dimensions with info before deciding whether (and how) to resize it avoids assuming every upload is already a reasonable size.
Real Format Support Limits
| Supported | Not Supported |
|---|---|
| JPEG, GIF, WEBP, TIFF, PNG, BMP | Animated GIF, multipage TIFF, PSD, AI |
WebP support was only added in the ColdFusion 2025 release, code relying on it needs that version or later.
A Real Lucee Naming Trap: isBase64 vs base64
Lucee's writeToBrowser documents a base64 attribute that embeds the output image inline as a base64 data URL. That's a completely different setting from isBase64, which indicates the source input is already Base64-encoded. The two names are easy to confuse but control opposite ends of the operation.
Common Beginner Mistakes
Confusing isBase64 with Lucee's base64 attribute
isBase64 says the source is Base64-encoded. Lucee's base64 (on writeToBrowser) instead embeds the output as a base64 data URL, they control opposite ends of the operation.
Assuming WebP works on any ColdFusion version
It was only added in the ColdFusion 2025 release, code targeting an earlier version needs a different format.
Assuming an animated GIF's frames or a multipage TIFF's pages are preserved
Neither is supported, cfimage operates on a single still image, not multi-frame or multi-page formats.
Forgetting destination is required for convert/write but name is required for read
Each action has its own required output attribute, using the wrong one for a given action leaves the result nowhere to go.
Best Practices
- Use action="info" to inspect an uploaded image (dimensions, format) before deciding how to process it.
- Set overwrite explicitly when regenerating a processed image repeatedly, like a thumbnail.
- Choose interpolation deliberately, trading resize quality against performance rather than accepting the default everywhere.
- Validate an uploaded file's actual format against cfimage's real supported list before attempting to process it.
Interview Questions
What does cfimage's action attribute default to?
read.
Why might code using format="webp" fail on an older ColdFusion server?
WebP support was only added in the ColdFusion 2025 release, it isn't available on earlier versions.
On Lucee, what's the difference between isBase64 and base64?
isBase64 indicates the source input is already Base64-encoded. base64 (on writeToBrowser) instead embeds the output image as a base64 data URL, an easy naming mix-up since they apply to opposite ends of the operation.
Would cfimage preserve every frame of an animated GIF?
No, animated GIF (along with multipage TIFF, PSD, and AI) isn't supported, cfimage operates on a single still image.
Summary
In this lesson, you resized, rotated, and bordered an image, generated a CAPTCHA, read an image's metadata before processing it, and covered real format support limits, WebP's ColdFusion 2025 requirement, and a genuine isBase64-vs-base64 naming trap on Lucee.
What's Next?
The next lesson covers cfschedule, scheduling a task to run automatically on a recurring basis.