Leave That Thing Alone Blog

Viewing By Entry / Main
6 Apr. 2008

Here's a quick example of how to open and/or view a multipage TIFF with ColdFusion 8. This example requires no external Java libraries.

The first step is to open the multi-page tiff and using the JAI ImageCodec we're able to determine the number of pages in that tif and create an array of the pages.

<cfscript>
   //set TIFF file name
   tifFileName = expandpath('samples\patent.tif');
   //create FileSeekableStream
   ss = createObject("Java","com.sun.media.jai.codec.FileSeekableStream").init(tifFileName);
   //create JAI ImageDecoder
   decoder = createObject("Java","com.sun.media.jai.codec.ImageCodec").createImageDecoder("tiff", ss, JavaCast("null",""));
   //create array
   tifPageArray = arrayNew(1);
   //loop through pages of tiff add to array
   for (i=0;i<decoder.getNumPages();i++) {
      //add each to array (com.sun.media.jai.codecimpl.TIFFImage)
      tifPageArray[i+1] = decoder.decodeAsRenderedImage(i);
   }
</cfscript>

At this point we have array of tiff images (of type com.sun.media.jai.codecimpl.TIFFImage). Based on your needs your code will probably need to change after this. To be able to easliy 'use' these TIFF pages in ColdFusion we need to convert them to the cfimage format. One of the great features about the ColdFusion 'imageNew' tag is that it accepts BufferedImage as an input

So to move from TIFF to cfimage we do this:
TIFF -> PlanarImage -> BufferedImage -> cfimage

Here's some code to loop though all the pages and write a JPG for each page in the mulitpage tiff:

<cfscript>
   //loop through all tiff pages
   for (i=0;i<decoder.getNumPages();i++) {
      //create PlanarImage
      pImg = createObject("Java","javax.media.jai.PlanarImage").wrapRenderedImage(tifPageArray[i+1]);
      //get buffered image
      bufferedImage = pImg.getAsBufferedImage();
      //use CF image tage to create CF image from bufferedImage
      myImage = imageNew(bufferedImage);
      //write image
      imageWrite(myImage,"page#i+1#.jpg");
   }
</cfscript>

You may want to alter the code above as writing TIFF pages to JPGs might not be what you need. After 'imageNew(bufferedImage)' we have a cfimage so you are able to do any ColdFusion 8 image function on the TIFF page.

Update:
Multi-Page Tiff support has now been added to ImageUtils

Comments

Excellent post! By chance is there a way to convert the TIFF images to PDF? I've done that with GhostScript using a simple call to the command line. I wonder if this could be done by going from cfimage to cfdocument or cfpdf.


@Adrian

Here's a way to create a PDF once you've got the array of TIFF pages. This is surely not the best approach as a large number of pages may cause memory issues:

<cfdocument format="PDF">
   <cfloop from="1" to="#decoder.getNumPages()#" index="i">
      <cfscript>
         //create PlanarImage
         pImg = createObject("Java","javax.media.jai.PlanarImage").wrapRenderedImage(tifPageArray[i]);
         //get buffered image
         bufferedImage = pImg.getAsBufferedImage();
         //use CF image tage to create CF image from bufferedImage
         myImage = imageNew(bufferedImage);
      </cfscript>
      <cfdocumentsection>
         <cfimage action="writetobrowser" source="#myImage#" />
      </cfdocumentsection>
   </cfloop>
</cfdocument>


Hi Seth,
nice example! There is an updated Version of imageUtils.cfc available on RIAForge.org, which also supports multipage tiffs ;)


@Patrick

Yeah i see that just got added to imageUtils.cfc, it has some nice features. More complete than this example which is great.


I've looked at the code and it seems that I can follow it pretty well. I have three features that I want to add. The first is to TiffSplit(). I want to take a 500+ multi-page tiff and split it into 100 plag files.

Then I want a TiffJoin() where I can have several single page tiffs and put them all into one file.

Finally, a PDFToTiff() where a multi-page PDF file can be put into a multi-page tiff.

Items one and twop seem like they might be pretty simple. On item three, I have no idea how simple or not this might be able to do.

Can you give an idea on the best way to code item one and two?