A reader asked me this morning if ColdFusion 8 can create images from URLs. This is often used to provide a snap shot of a remote site. Turns out this is relatively easy. Damon Cooper of Adobe showed an example of this a few weeks ago. It takes all of two tags:
1 <cfdocument src="http://www.coldfusionjedi.com" name="pdfdata" format="pdf" />
2 <cfpdf source="pdfdata" pages="1" action="thumbnail" destination="." format="jpg" overwrite="true" resolution="high" scale="25">
The first line simply uses cfdocument with the src attribute. I point to a URL (in this case, my blog) and store the result in a PDF variable.
Next I use the cfpdf tag to create a thumbnail. I specify the JPG format, use a high resolution, and set a scale to 25% just for the heck of it. Also note I only do page 1. By default the cfpdf/action="thumbnail" tag will create a thumbnail for each page of the PDF, but all we really want is the first page.
That's it. Done. Complete. Simple as pie. But of course I had to go a bit crazy and make a UDF out of it. The code below allows you to pass a URL (and an optional scale). It will then handle making the image, reading it into a CF8 Image object, deleting the file, and returning the object. You can then save it, or do whatever. For my tests, I did:
2 <cfpdf source="pdfdata" pages="1" action="thumbnail" destination="." format="jpg" overwrite="true" resolution="high" scale="25">
1 <cfset myimage = getThumbnail("http://www.coldfusionjedi.com",30)>
2 <cfimage action="writeToBrowser" source="#myimage#">
The "writeToBrowser" action lets me test without actually saving a file, but I believe it doesn't work in IE. (Not that I care.) Enjoy, and let me know how it works for you. I'll probably add options to let you specify an image type as well.
The image quality is pretty good I think. It is not the same as what you see from Firefox, but for a thumbnail, I think it works ok:
2 <cfimage action="writeToBrowser" source="#myimage#">
1 <cffunction name="getThumbnail" returnType="any" output="false">
2 <cfargument name="url" type="string" required="true">
3 <cfargument name="scale" type="numeric" required="false" default="25">
4
5 <cfset var pdfdata = "">
6 <cfset var prefix = replace(createUUID(),"-","_","all")>
7 <cfset var myimage = "">
8
9 <!--- make the pdf --->
10 <cfdocument src="#arguments.url#" name="pdfdata" format="pdf" />
11
12 <!--- write out the image --->
13 <cfpdf source="pdfdata" pages="1" action="thumbnail" destination="." format="jpg" overwrite="true"
14 resolution="high" scale="#arguments.scale#" imagePrefix="#prefix#">
15
16 <!--- read it in --->
17 <cfset myimage = imageNew(expandPath('./#prefix#_page_1.jpg'))>
18
19 <!--- clean it up --->
20 <cffile action="delete" file="#expandPath('./#prefix#_page_1.jpg')#">
21 <cfreturn myimage>
22 </cffunction>
2 <cfargument name="url" type="string" required="true">
3 <cfargument name="scale" type="numeric" required="false" default="25">
4
5 <cfset var pdfdata = "">
6 <cfset var prefix = replace(createUUID(),"-","_","all")>
7 <cfset var myimage = "">
8
9 <!--- make the pdf --->
10 <cfdocument src="#arguments.url#" name="pdfdata" format="pdf" />
11
12 <!--- write out the image --->
13 <cfpdf source="pdfdata" pages="1" action="thumbnail" destination="." format="jpg" overwrite="true"
14 resolution="high" scale="#arguments.scale#" imagePrefix="#prefix#">
15
16 <!--- read it in --->
17 <cfset myimage = imageNew(expandPath('./#prefix#_page_1.jpg'))>
18
19 <!--- clean it up --->
20 <cffile action="delete" file="#expandPath('./#prefix#_page_1.jpg')#">
21 <cfreturn myimage>
22 </cffunction>
Comment 1 written by Scott Stroz on 13 June 2007, at 1:03 PM
Comment 2 written by Raymond Camden on 13 June 2007, at 1:06 PM
Comment 3 written by Damien McKenna on 13 June 2007, at 1:56 PM
Comment 4 written by Damien McKenna on 13 June 2007, at 1:57 PM
Comment 5 written by Clark on 13 June 2007, at 2:49 PM
Comment 6 written by David Harris on 13 June 2007, at 3:01 PM
I've been wanting to be able to do that for ages!
BD has a "jpg" format on their cfdocument, I was hoping Adobe would think this was a good idea too!
Comment 7 written by Raymond Camden on 13 June 2007, at 3:09 PM
Comment 8 written by Dale Fraser on 13 June 2007, at 5:20 PM
I knew if there was a way you would know how.
I think the quality is prety good, and while the CFDocument might not render every element perfectly, which browser does?
If you add in some IMAGE tags to dress up the final result, crop, put a border etc, would work well in lots of situations.
Comment 9 written by Justin Lewis on 13 June 2007, at 10:12 PM
I'll try it out and check out how much megahurtz it steels.
Comment 10 written by Raul Riera on 14 June 2007, at 7:57 AM
Comment 11 written by Tom Jordahl on 14 June 2007, at 3:44 PM
Should work in any browser.
Comment 12 written by Raymond Camden on 14 June 2007, at 3:48 PM
Comment 13 written by Dwayne Anderson on 20 June 2007, at 5:02 PM
error:Attribute validation error for tag CFDOCUMENT.
Comment 14 written by Raymond Camden on 20 June 2007, at 5:06 PM
Comment 15 written by Dwayne Anderson on 20 June 2007, at 5:16 PM
Comment 16 written by Dwayne Anderson on 20 June 2007, at 5:18 PM
Comment 17 written by Raymond Camden on 20 June 2007, at 5:22 PM
Comment 18 written by BL on 9 July 2007, at 10:47 PM
Comment 19 written by Dave Phipps on 11 July 2007, at 7:52 AM
Comment 20 written by CV on 3 September 2007, at 3:07 PM
Here are a few sample URLs that get a little funky:
http://www.caraccessories.com/
http://www.partstrain.com/
Is this worthy of another blog entry?
Comment 21 written by Raymond Camden on 4 September 2007, at 1:55 PM
Comment 22 written by Brett on 17 September 2007, at 10:44 AM
Comment 23 written by Raymond Camden on 17 September 2007, at 10:48 AM
One is support. I don't know if that is free or not. I've only ever called support when I needed help with my CS3 install (oh god, the pain, the pain!). You would use that option if you need something fixed now.
If you just want to file a bug report, then go to www.adobe.com/go/wish. You can also use that URL to request a new feature.
Comment 24 written by Solomon on 1 October 2007, at 3:22 AM
Comment 25 written by Doug Jones on 22 April 2008, at 2:52 PM
At least that's been my observation. Still very cool.
Comment 26 written by Mike on 29 August 2008, at 4:16 AM
I just tried this, and using the exact code in your eg there im seeing this exception
writeToBrowser:
coldfusion.image.Image$ReadImageMetadataException: Unable to read image source properly. D:\Domains\xxxxxx.com\wwwroot\0DBCEC5F_19B9_F849_B29064C59F3AC984_page_1.jpg (The system cannot find the file specified)
any ideas why this wouldnt work?
Comment 27 written by Raymond Camden on 30 August 2008, at 9:53 AM
Comment 28 written by Raymond Camden on 30 August 2008, at 10:04 AM
<cfreturn imageGetBlob(myimage)>
This makes the UDF return the binary data of the image, not a 'native cf image' which is barfing when you try to use it. It barfs because we delete the original temp source we used. As I said, something must have changed in 801.
Anyway, the binary data CAN be used with writeToBrowser, or you can save it, whatever. Either way, it's fixed now.
Comment 29 written by Jeff Horne on 11 September 2008, at 9:38 AM
Comment 30 written by Raymond Camden on 11 September 2008, at 9:40 AM
Comment 31 written by Tim Mortimer on 14 September 2008, at 4:36 PM
Always find your blogs useful. A related question to this thread - whats the easiest way to convert CFML output or text to an image in CF?
Tim
Comment 32 written by Raymond Camden on 14 September 2008, at 9:12 PM
Comment 33 written by Freemont on 6 February 2009, at 12:20 PM
[Add Comment] [Subscribe to Comments]