Posted in ColdFusion | Posted on 09-14-2007 | 3,770 views
Todd Sharp recently pinged me about an interesting problem. He was working with Images generated in ColdFusion 8 and was trying to use this imaga via the HTML IMG tag, like so:
The code in foo.cfm generated the graphic and he couldn't quite figure out how to display it. One thing he tried was the WriteToBrowser action:
This didn't work - and if you view source on a file using this action you will see why. The WriteToBrowser action actually generates HTML that points to a 'magic' URL to serve the image.
He also tried cfcontent:
2<cfcontent type="image/jpg" variable="#paris#">
This also failed as well. Why? The cfcontent tag doesn't like the Image variable. ColdFusion will throw the following error:
coldfusion.image.Image is not a supported variable type. The variable is expected to contain binary data.
If you think about it - this makes sense. Image variables aren't binary data in ColdFusion. While they may store binary data, ColdFusion wraps up the data in a new "Image" variable type. Now personally I think cfcontent should be smart enough to recognize a image variable and deal with it - but what do you in the meantime?
ColdFusion provides a ImageGetBlob function. This returns the binary data of the image and can be safely used with cfcontent like so:
2<cfcontent type="image/jpg" variable="#imageGetBlob(paris)#">
But wait - there is a catch! This works ok as long as you begin your image with a real image. Notice above I have a image file I'm beginning with. If I use a 100% virtual image then it doesn't work. Consider:
If you run imageGetBlob on this, you get:
The source file should contain an extension,so that ColdFusion can determine the image format.
So I'm not 100% sure - but this is how I read this. I had created an image of a certain type of image type. But there was no file type for the image. Obviously I could write the variable out to a file, but there is no way to go directly from an "pure" Image variable to a blob. I'm going to file an enhancement request to add support for this. In the meantime if you needed to do something like this, I'd recommend creating a "canvas" graphic in your desired format and seed your dynamic image with that.
Ok - so now for the contest part. I whipped up a quick demo to show the code described above in action. I call it the Paris-Talkometer. Let me show you the code and then I'll link to the application.
2
3<cfajaxproxy bind="javascript:updImage({caption})">
4
5<script>
6function updImage(str) {
7 if(str != '') document.getElementById('myimg').src = 'imgs3.cfm?caption='+escape(str);
8}
9</script>
10
11<h2>Paris-Talkometer</h2>
12
13<cfform name="form">
14<cfinput type="text" name="caption" value="#url.caption#" > <cfinput name="mybutton" type="button" value="Update"><br />
15<cfinput type="image" name="myimage" src="imgs3.cfm?caption=#url.caption#" id="myimg">
16</cfform>
What we have is is a basic form. There is a text box for a caption, and a cfinput image type that points to imgs3.cfm. Notice though that it passes a URL variable. Go back up to the top of the file and see how I use cfajaxproxy to bind to the caption. Whenever the caption changes, I use a bit of JavaScript to the change the SRC of the image. Here is the code behind imgs3.cfm:
2
3<cfimage action="read" source="paris.jpg" name="paris">
4
5<cfif len(trim(url.caption))>
6
7 <cfset imageSetDrawingColor(paris, "black")>
8 <cfset imageDrawRect(paris, 1, 1, paris.width, 40, true)>
9
10 <cfset imageSetAntialiasing(paris, "on")>
11 <cfset imageSetDrawingColor(paris, "white")>
12 <cfset text = { style='bold', size=12, font='verdana' }>
13 <cfset imageDrawText(paris, url.caption, 10, 25, text)>
14
15</cfif>
16
17<cfcontent type="image/jpg" variable="#imageGetBlob(paris)#">
All I'm really doing here is looking for a URL.caption value. If it exists, I draw some text over the picture. The last thing I do is serve up the image using cfcontent and imageGetBlob.
You can see this in action here:
http://www.coldfusionjedi.com/demos/imagecfcontent/test3.cfm
Now for the contest. If you look at the code for test3.cfm, you will notice that you can seed the caption value via the URL. Here is an example.
Your content is to make Paris intelligent - or at least witty. While this is a somewhat herculean task - I'm sure some of you can do it. Just post your URL as a comment (and of course, you can comment on the main part of this blog post as well). Please keep your captions work safe. Work safe doesn't mean boring - just keep it safe please.


If you save the image file to the HDD and use a server side redirect or a cflocation redirect to the image file I believe it should work.
Cheers!
Actually, I mentioned if you _start_ with a real file you are good. So yes - this is an alternative as well.
http://www.coldfusionjedi.com/demos/imagecfcontent...!
Anyone who's been to a sheep & wool festival will see the absurdity and irony in that comment, considering who Paris Hilton is. ;-)
"Did you know they named a city after me" LMFAO awesome!
As far as I know, the no way to "measure" your text. Let me kick some people around and see if I can get any info on that.
http://www.coldfusionjedi.com/demos/imagecfcontent... me! I'm trapped in your computer!
http://www.coldfusionjedi.com/demos/imagecfcontent... I do look pretty fine in here
(to be viewed one after the other) ;)
enjoy..
i feel silly now :)
Let's try again: http://www.coldfusionjedi.com/demos/imagecfcontent......?
http://www.coldfusionjedi.com/demos/imagecfcontent...
I know you don't like using undocumented features :-)
But here is something very simple you can use which will work in all the cases. You can use getImageBytes() method on image object.
<cfset canvas = imageNew("", 100, 100, "rgb", "red")>
<cfset bytes = canvas.getImageBytes("jpg")>
<cfcontent type="image/jpg" variable="#bytes#">
Cheers !
Rupesh.
Rupesh - I didn't get a chance to file a ER. I'll do so now.
www.coldfusionjedi.com/demos/imagecfcontent/test3....
Here is the above link in tiny form.
http://tinyurl.com/34qs3u
Regarding the text measuring... there's no way in CF8 to do it natively but you can write a few lines of Java code to do it for you and call that from your CF code. I wrote a Font CFC to do this, as well as determining whether or not text will fit in a given rect size, etc. It doesn't reformat the text to fit inside a rect (it's on the TODO list) but it's quite accurate and supports different font families, sizes and styles.
Once I get home this evening I can upload it someplace and give the URL here if you're interested. The code is still pretty dirty as it's still in development, but it works.
George.
http://homepage.mac.com/georgebridgeman/FontUtil.c...
I'll finish it off if I get some time. You should be able to get the jist of it though, even though it's quite mucky.
<cfcontent type="image/jpg" variable="#imageGetBlob(myimage)#">
the quality of the rendered image is quite bad. Is there any way on how to render a image with a better quality?
[Add Comment] [Subscribe to Comments]