Thursday, January 3, 2008

How to fill text with an Image using ColdFusion (and a little java)

I discovered a trick you can use to fill text with an image, using ColdFusion 8's image functions, and a little help from java. Now with my image, I wanted to use a specific area of it for filling the text. You will see why below. So first I used the ImageCopy function to grab a rectangular slice of the source image.


<cfset sliceWidth = 600>
<cfset sliceHeight = 60>
<cfset sourceImage = ImageNew( ExpandPath("combustion.jpg") )>
<cfset sliceImage = ImageCopy(sourceImage, 30, 192, sliceWidth, sliceHeight)>


As you can see this is source image I used. To make it easier to visualize, the rectangular slice area is outlined in white.


Original image by ShadowLight


Next I created a new image and drew my text on it, using antialiasing to produce smoother text edges. It is worth noting the text color does not matter since the text will ultimately be filled with the image slice graphic.


<cfset maskImage = ImageNew("", sliceWidth, sliceHeight, "argb")>
<cfset ImageSetAntiAliasing( maskImage, "on") >
<cfset ImageSetDrawingColor( maskImage, "white")>
<cfset attr = { Size = 35, Font = "Arial", Style= "boldItalic" }>
<cfset ImageDrawText(maskImage, "FLAME AND COMBUSTION", 65, 40, attr)>


Finally, I used a little java to achieve the fill effect. This was done by using an AlphaComposite when drawing the image over the text mask. The result is only the parts of the image that overlap with the text are rendered.


<cfscript>
maskGraphics = ImageGetBufferedImage(maskImage).getGraphics();
AlphaComposite = createObject("java", "java.awt.AlphaComposite");
maskGraphics.setComposite( AlphaComposite.SrcIn );
maskGraphics.drawImage( ImageGetBufferedImage(sliceImage),
javacast("int", 0),
javacast("int", 0),
javacast("null", ""));
maskGraphics.dispose();
</cfscript>

<div style="background-color: black; ">
<cfimage source="#maskImage#" action="writeToBrowser">
</div>


Here is the result. For this image I used a black background for better contrast.



Now if it does not matter which part of the image is used, you could skip the ImageCopy and simply draw the graphic over the text at position (0, 0) like this:


<cfset sourceImage = ImageNew( "c:\img\myImage640x480.jpg" )>
<cfset maskImage = ImageNew("", 500, 70, "argb")>
<cfset ImageSetAntiAliasing( maskImage, "on") >
<cfset ImageSetDrawingColor( maskImage, "white")>
<cfset attr = { Size = 30, Font = "Arial", Style= "boldItalic" }>
<cfset ImageDrawText(maskImage, "HORIZON OF SKY AND CLOUDS", 20, 40, attr)>

<cfscript>
// cfSeaching: use a composite to render only the parts of the image that overlap with the text mask
maskGraphics = ImageGetBufferedImage(maskImage).getGraphics();
AlphaComposite = createObject("java", "java.awt.AlphaComposite");
maskGraphics.setComposite( AlphaComposite.SrcIn );
maskGraphics.drawImage( ImageGetBufferedImage(sourceImage),
javacast("int", 0),
javacast("int", 0),
javacast("null", ""));
maskGraphics.dispose();
</cfscript>

<!--- show original and mask image side by side --->
<cfimage source="#sourceImage#" action="writeToBrowser">
<cfimage source="#maskImage#" action="writeToBrowser">


Hope you found this useful. Comments, suggestions, corrections are always welcome.

5 comments:

Anonymous,  June 6, 2008 at 2:16 AM  

it did not woeked as suggested by you, the image text appears bu the background image get disaapear, is some logic behind this:

cfSearching June 13, 2008 at 11:46 AM  

@Gary,

Yes, that is the idea here. ie To display the text only, without the background.

Perhaps you are trying to achieve something different.. Can explain more about what you are trying to do with the code?

Nick,  September 30, 2009 at 12:44 AM  

I would like to do something similar but instead of an select an image as the background fill for the text, I would like to have a transparent background. ie. only show a border from the text. Similar to the nofill function in publisher. Any suggestions?

cfSearching October 1, 2009 at 10:34 AM  

@Nick,

So everything is transparent, except for the outline of the text?

Yes, that is possible. Let me write up an example .. just because it is a cool technique ;)

-Leigh

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep