Friday, April 4, 2008

Determining which image formats are supported by your JVM

This entry is a mainly reminder to myself about image formats.

Before ColdFusion 8 introduced its built-in image functions, creating images took a bit more work. You normally had to tap into the underlying java classes to read and write images. One thing I always forget is how to determine which image formats are supported. Typically it is determined by the JVM version. To read or write a specific type of image (like GIF, PNG, TIFF, etcetera) an appropriate reader or writer must be registered with the JVM.

ColdFusion 8 ships with JVM 1.6. Out of the box, 1.6 is capable of reading and writing a lot of different image formats, such as GIF and TIFF. However, earlier versions of ColdFusion usually shipped with JVM 1.42. Unfortunately, version 1.42 is much more limited. For example, it can read GIF images but cannot write them. So it good to know which JVM you are using and which readers and writers are registered.


Addendum: Though ColdFusion 8 can write/create gif images, there is a known issue with creating transparent gif's from scratch. When the image is saved, transparent backgrounds are lost. The image is saved with a black background. I think this is a known issue with the underlying java image classes. However there is a work-around for this issue. See Creating Transparent GIF's with ColdFusion 8.


Display ColdFusion's JVM version

<cfset version = createObject("java", "java.lang.System").getProperty("java.version")>
<cfdump var="#version#">


Display image readers and writers registered with ColdFusion's JVM

<cfset ImageIO = createObject("java", "javax.imageio.ImageIO")>
<cfdump var="#ImageIO.getReaderFormatNames()#" label="ReaderFormatNames"><br>
<cfdump var="#ImageIO.getReaderMimeTypes()#" label="ReaderMimeTypes"><br>
<cfdump var="#ImageIO.getWriterFormatNames()#" label="WriterFormatNames"><br>
<cfdump var="#ImageIO.getWriterMIMETypes()#" label="WriterMIMETypes"><br>


The results should look something like the image below. The exact values displayed will vary depending on your JVM version. "FormatNames" are similiar to a file extension name, like "jpeg" or "gif". Consider them an informal way of referring to the MIME type when using certain methods of java's ImageIO class.



For those who have never used java to read/write images, here are a few simple examples. Bear in mind I am posting them for the curious. Since image functions are already built into ColdFusion 8, there is typically little need to use java directly. For MX6/7 there are several robust image handling options (that handle the java for you), such as Rick Root's ImageCFC. No need to reinvent the wheel ;)

Read an Image from a URL

<cfscript>
// construct the URL of the image to read
urlString = "http://www.google.com/press/images/logos/google_desktop_sm.jpg";
imageURL = createObject("java", "java.net.URL").init( urlString );
// read the image from the URL
ImageIO = createObject("java", "javax.imageio.ImageIO");
image = ImageIO.read( imageURL );
// write out the image bytes
byteStream = createObject("java", "java.io.ByteArrayOutputStream").init();
wasWritten = ImageIO.write( image, "jpeg", byteStream);
</cfscript>

<cfif wasWritten>
<!--- NOTE: The variable attribute requires MX7+ --->
<cfcontent type="image/jpeg" variable="#byteStream.toByteArray()#">
<cfelse>
Image format not supported
</cfif>


Read a Local Image File

<!--- read a local image file --->
<cfscript>
// construct a File object representing the image on disk
pathToImage = ExpandPath("sourceImageFile.jpg");
imageFile = createObject("java", "java.io.File").init( pathToImage );
// read the image from the File
ImageIO = createObject("java", "javax.imageio.ImageIO");
image = ImageIO.read( imageFile );
// write out the image bytes
byteStream = createObject("java", "java.io.ByteArrayOutputStream").init();
wasWritten = ImageIO.write( image, "jpeg", byteStream);
</cfscript>

<cfif wasWritten>
<!--- NOTE: The variable attribute requires MX7+ --->
<cfcontent type="image/jpeg" variable="#byteStream.toByteArray()#">
<cfelse>
Image format not supported
</cfif>


Read Image from a URL and Save it to a File

<cfscript>
saveToFile = ExpandPath("./name_of_saved_image.jpg");
// Construct the URL of the image to read
urlString = "http://www.google.com/press/images/logos/google_desktop_sm.jpg";
imageURL = createObject("java", "java.net.URL").init( urlString );
// Read the image from the URL
ImageIO = createObject("java", "javax.imageio.ImageIO");
image = ImageIO.read( imageURL );
// Save the image to a local file
outStream = createObject("java", "java.io.FileOutputStream").init( saveToFile );
wasWritten = ImageIO.write( image, "jpeg", outStream);
outStream.close();
</cfscript>

<cfif wasWritten>
<!--- display the local image --->
<cfoutput>
<img src="#saveToFile#">
</cfoutput>
<cfelse>
Image format not supported
</cfif>

2 comments:

Anonymous,  April 5, 2008 at 5:08 AM  

This is a very informative post in my opinion as are others you have here on your blog. So few of the posts around on ColdFusion cover the JVM and it is good to see what you are doing on that subject.

cfSearching April 5, 2008 at 7:21 AM  

Thank you!

Yes, when I began interacting with java from ColdFusion I was unaware there were so many differences between JVM's. It has been interesting discovering what some of the differences are and how they can impact ColdFusion code. Especially when using image classes.

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep