ColdFusion 8 Image functions and text size

This post is more than 2 years old.

One of the things that I've been curious about for a while now is if there was a way to determine the graphical size of text when drawing in ColdFusion 8. Why would you need to care about that? While ColdFusion 8 lets you easily draw text on an image, there is no easy way to center it. In order to center it, you need to know the size of the text. Today in CF-TALK this issue came up in a thread.

A user named C S (not sure of his real name) provided the following code which works just dandy:

<cfscript> buffered = ImageGetBufferedImage(theColdFusionImage); context = buffered.getGraphics().getFontRenderContext(); Font = createObject("java", "java.awt.Font"); // font name, style and size textFont = Font.init( "Arial", Font.ITALIC, javacast("int", 15)); textLayout = createObject("java", "java.awt.font.TextLayout").init( text, textFont, context); textBounds = textLayout.getBounds(); dimen.width = textBounds.getWidth(); dimen.height = textBounds.getHeight(); </cfscript>

<cfdump var="#dimen#">

Ben Nadel then chimed in and pointed out a cool blog entry where he describes how you can take a text string, provide a bounding box, and his UDF will wrap the text correctly within the box. His work was inspired by yet another blog post by Barney Boisvert.

With me so far? ;) So the issue of centering text now becomes simple. When you draw text, the X and Y represent the bottom left corner of the text block. So to center, you simply place the X at: Canvas Width/2 - Text Width/2. Height is the reverse: Canvas Height/2 + Text Height/2.

Here is a complete example. If you change the text, it should re-center accordingly.

<cfset canvas = imageNew("",500,500,"rgb","yellow")> <cfset text = "Paris Hilton kicks butt!">

<cfscript> buffered = ImageGetBufferedImage(canvas); context = buffered.getGraphics().getFontRenderContext(); Font = createObject("java", "java.awt.Font"); // font name, style and size textFont = Font.init( "Arial-Black", Font.ITALIC, javacast("int", 15)); textLayout = createObject("java", "java.awt.font.TextLayout").init( text, textFont, context); textBounds = textLayout.getBounds(); dimen.width = textBounds.getWidth(); dimen.height = textBounds.getHeight(); </cfscript>

<cfdump var="#dimen#">

<!--- when drawing text, you specify X, Y as the bottom left corner. So we need to position ourselves at Total Height / 2 + Height of Text / 2 ---> <cfset attr = { font="Arial-Black", size="15", style="italic"}> <cfset newx = (canvas.width/2 - dimen.width/2)> <cfset newy = (canvas.height/2 + dimen.height/2)> <cfset imageSetDrawingColor(canvas,"black")> <cfset imageDrawText(canvas,text, newx, newy, attr)>

<cfimage action="writeToBrowser" source="#canvas#">

There is a reason for all of this that I'll explain later in the week (for my Friday contest probably).

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by cfSearching posted on 1/18/2008 at 9:23 AM

If anyone is interested, I have been experimenting with a line wrap function that uses java's LineBreakMeasurer. I wrote up an entry on it here

http://cfsearching.blogspot...

Comment 2 by Dan B posted on 1/26/2008 at 1:08 AM

Hey Ray.. Has anyone found a way to "smooth out" and anti-alias fonts when adding text to an image? Is there an attribute that I might be missing? I created a dynamic last.fm badge using their audio scrobbler data feed and cfimage but the font leaves a lot to be desired.

See badge at: http://www.last.fm/user/djb...

Comment 3 by cfSearching posted on 1/26/2008 at 2:19 AM

Dan B,

Are you using the ImageSetAntialiasing function?
http://livedocs.adobe.com/c...

Comment 4 by Dan B posted on 1/26/2008 at 2:37 AM

SWEET! Exactly what I was looking for!

Comment 5 by Misty posted on 2/12/2012 at 1:20 PM

Hi ray, ran the same example in CF 9.0.1, and it throws error on Font, Says "Arial-Black" invalid font, i used then another font "Agency FB" and it worked.

Just to bring nto your notice

Cheers

Comment 6 by Raymond Camden posted on 2/12/2012 at 9:17 PM

Right, that is to be expected. Different machines will have different fonts available. We actually provide a function so you can check that programatically. (I think it is getAvailableFonts).

Comment 7 by Raymond Camden posted on 2/12/2012 at 9:40 PM

Shoot - I stand corrected. I thought we did expose available fonts. Doing some research.

Comment 8 by Raymond Camden posted on 2/12/2012 at 9:42 PM

You can use the code here to get the list of fonts dynamically:

http://cfsearching.blogspot...

Comment 9 by Misty posted on 2/13/2012 at 12:24 PM

Thanks Ray!

if i want to place the image just in the bottom middle what constraints i need to change

here is a fubction to list fonts installed

<cffunction name="getFontNames" access="public" returntype="array">
<cfset var allFonts = CreateObject("java", "java.awt.GraphicsEnvironment").getLocalGraphicsEnvironment().getAllFonts() />
<cfset var fontArray = ArrayNew(1) />
<cfset var i = "" />
<cfloop from="1" to="#ArrayLen(allFonts)#" index="i">
<cfset ArrayAppend(fontArray, allFonts[i].getName()) />
</cfloop>
<cfreturn fontArray />
</cffunction>

Comment 10 by Raymond Camden posted on 2/14/2012 at 3:32 AM

Please see the imageUtils project at RIAForge. It includes code that lets you "measure" a block of text graphically. This can be used for things like centering.