All you need is a new image that supports transparency. Next, grab the underlying graphics object from the image. You will be using it to draw the text outline onto the image.
<cfscript>
transparentImage = ImageNew("", width, height, "argb");
graphics = ImageGetBufferedImage(transparentImage).createGraphics();
</cfscript>
Now here is where you veer into the java code. The first step in the example is to enable antialiasing for smoother text. This is achieved with RenderingHints. If you are not familiar with them, think of them as java's version of ImageSetAntialiasing().
<cfscript>
RenderingHints = createObject("java", "java.awt.RenderingHints");
graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
graphics.setRenderingHint( RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY
);
</cfscript>
Next the example creates a graphical representation of the text. In other words, it gets the shape of the rendered text. This is done with a neat class called TextLayout. TextLayout handles all the hard work of positioning, spacing, text styles and generating the final glyphs.
<cfscript>
Font = createObject("java", "java.awt.Font");
textFont = Font.init("Arial", Font.PLAIN, width / 5 );
textColor = createObject("java", "java.awt.Color").decode("##80aa1c");
fontContext = graphics.getFontRenderContext();
layout = createObject("java", "java.awt.font.TextLayout").init(text, textFont, fontContext);
</cfscript>
But before the text shape can be drawn onto the image, it must be positioned. This is done with an AffineTransform. In this case it is a fancy way of saying move the x,y drawing coordinates. (I tweaked the code example to center the text).
<cfscript>
transX = (width/2) - (layout.getBounds().getWidth()/2);
transY = (height/2) + layout.getDescent();
transform = createObject("java", "java.awt.geom.AffineTransform").init();
transform.setToTranslation( transX, transY );
</cfscript>
Finally, the example grabs the shape of the text, sets the text color and draws the outline onto the image. That is all there is to it.
<cfscript>
shape = layout.getOutline(transform);
graphics.setColor(textColor);
graphics.draw(shape);
graphics.dispose();
</cfscript>
Full Code
<cfscript>
width = 330;
height = 150;
text = "Crossfade";
// Create a new image that supports transparency
transparentImage = ImageNew("", width, height, "argb");
graphics = ImageGetBufferedImage(transparentImage).createGraphics();
// Add rendering hints to smooth text edges
RenderingHints = createObject("java", "java.awt.RenderingHints");
graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
graphics.setRenderingHint( RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY
);
// Create a graphical representation of the text
Font = createObject("java", "java.awt.Font");
textFont = Font.init("Arial", Font.PLAIN, width / 5 );
textColor = createObject("java", "java.awt.Color").decode("##80aa1c");
fontContext = graphics.getFontRenderContext();
layout = createObject("java", "java.awt.font.TextLayout").init(text, textFont, fontContext);
// Center text outline
transX = (width/2) - (layout.getBounds().getWidth()/2);
transY = (height/2) + layout.getDescent();
transform = createObject("java", "java.awt.geom.AffineTransform").init();
transform.setToTranslation( transX, transY );
// Draw the text outline onto the image
shape = layout.getOutline(transform);
graphics.setColor(textColor);
graphics.draw(shape);
graphics.dispose();
</cfscript>
<cfoutput>
<!--- display raw image --->
<cfimage source="#transparentImage#" action="writeToBrowser">
<!--- display WITH background --->
<div style="background-color: ##000080; width: #width#; height=#height#;">
<cfimage source="#transparentImage#" action="writeToBrowser">
</div>
</cfoutput>
This is great. Exactly what I wanted.
ReplyDeleteThank you so much. Just another thing on it. Is it possible to use this image as a watermark in a pdf using cfpdf action=addwatermark?
@Nick,
ReplyDeleteTry it and find out ;-) But I do not see why not. It is just a transparent image, nothing special.
-Leigh
Hi Leigh
ReplyDeletecfpdf action=addwatermark didn't seem to work. It puts a gray shaded background instead. Also seems like the text inside is not readable. Looks like a bug in cf8. Not tried on cf9 as yet.
@Nick,
ReplyDeleteI forgot about cfpdf's issues with transparent images. It was fixed in the CF9 beta. For CF8, try using iText
http://cfsearching.blogspot.com/2009/06/cfpdf-issues-when-using-transparent.html
-Leigh