Friday, December 14, 2007

How to display an image icon on a form button using iText

I came across a question on one of the ColdFusion forums today, about how to change a form button to display an image icon. There is good java example demonstrating how to do this on www.lowagie.com. The code is quite simple and it works well, so I thought I would share the ColdFusion translation for anyone that might wish to do this.

The example uses two methods that were not introduced until sometime after iText 1.4. So once again I am using Mark Mandel's nifty JavaLoader.cfc to load a newer version of iText: 2.0.7.

Steps
1. Download the iText-2.0.7.jar available at sourceforge.net. The code may work with other jar versions but was only tested with 2.0.7

2. Download and install the JavaLoader.cfc available at javaloader.riaforge.org/.

3. Download the pushbutton.pdf sample file from the iText site. Its a simple form with a gray button.

Modify the paths in the sample code if needed. For simplicity, I placed my files in the same directory as the .cfm script


fullPathToInputFile = ExpandPath("./PushButton.pdf");
fullPathToOutputFile = ExpandPath("./PushButtonWithImage.pdf");
fullPathToITextJar = ExpandPath("./iText-2.0.7.jar");
dotNotationPathToJavaLoader = "com.javaloader.JavaLoader";


The result should create a new PDF file with the simple gray form button transformed to a button showing the google logo.



I used the google logo for the example because its accessible to everyone. But you can use an image on your local file system. See the notation in the code below.



UPDATE: The code sample below creates a new instance of the JavaLoader on each request. It is recommended that you store the javaLoader in the server scope instead to avoid memory leaks caused by a bug in ColdFusion. To find out more about this issue read Mark Mandel's article Using a Java URLClassLoader in CFMX Can Cause a Memory Leak.



<h1>Change a button to display an image icon Example</h1>
<cfscript>
/*
cfSearching:

My files are located in the current directory and
the Javaloader.cfc is located here:
C:\CFusionMX7\wwwroot\com\javaloader\JavaLoader.cfc

Your paths may be different
*/
fullPathToInputFile = ExpandPath("./PushButton.pdf");
fullPathToOutputFile = ExpandPath("./PushButtonWithImage.pdf");
fullPathToITextJar = ExpandPath("./iText-2.0.7.jar");
dotNotationPathToJavaLoader = "com.javaloader.JavaLoader";
// cfSearching: This is the button name in the PushButton.pdf file
buttonName = "PushMe";

// cfSearching: Create an instance of the javaloader
pathsForJavaLoader = arrayNew(1);
arrayAppend(pathsForJavaLoader, fullPathToITextJar);
javaLoader = createObject('component', dotNotationPathToJavaLoader).init(pathsForJavaLoader);

// cfSearching: Using the google logo for this example. Why? Because
// cfSearching: every can access it and see the correct results
imageURL = createObject("java", "java.net.URL").init(
"http://www.google.com/intl/en_ALL/images/logo.gif");

outStream = createObject("java", "java.io.FileOutputStream").init(fullPathToOutputFile);
pdfReader = javaloader.create("com.lowagie.text.pdf.PdfReader").init(fullPathToInputFile);
stamper = javaloader.create("com.lowagie.text.pdf.PdfStamper").init(pdfReader, outStream);
img = javaloader.create("com.lowagie.text.Image").getInstance(imageURL);

// cfSearching: To use a local image file, replace the previous line with the one below
// img = javaloader.create("com.lowagie.text.Image").getInstance(theFullPathToYourImageFile);

formFields = stamper.getAcroFields();
PushbuttonField = javaloader.create("com.lowagie.text.pdf.PushbuttonField");
bt = formFields.getNewPushbuttonFromField(buttonName);
bt.setLayout(PushbuttonField.LAYOUT_ICON_ONLY);
bt.setProportionalIcon(true);
bt.setImage(img);
bt.setIconFitToBounds(true);
formFields.replacePushbuttonField(buttonName, bt.getField());
stamper.close();
</cfscript>

3 comments:

Anonymous,  April 23, 2008 at 12:44 AM  

Can this work with unknown image sizes?

eg: In your example PDF you have a smallish button, if the user wishes to upload a large image, will the "button" change it's dimensions accordingly? or will the image be the same size as the orginal button in the PDF?

cfSearching April 24, 2008 at 3:17 PM  

No, the button will not change its dimensions. Only the image will be scaled.

You could resize the button, based on the image dimensions. However, that may require repositioning the button. ie To recenter it or so the button does not shift off the page, etcetera.

cfSearching April 24, 2008 at 3:18 PM  

Depending on your goal, using an image object instead of a button may be more appropriate.

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep