Resizing an image with CFImage (Creating a Thumbnail)
Coldfusion, cfimageYesterday, I got an email asking for some help on using CFImage to create thumbnails on a image that was submitted / uploaded through a form. Here's a quick and dirty example of how to do just that.
<cfif Isdefined('form.FileUpload') and form.FileUpload NEQ ''>
<!--- upload the image file from the form submission --->
<cffile action="upload"
fileField="FileUpload"
destination="#ExpandPath('/dev/images/')#"
nameconflict="makeunique">
<!--- Read the image, this only needs to be done once --->
<cfimage name="TempImage"
source="#cffile.ServerDirectory#/#cffile.ServerFile#"
action="read">
<!--- store image properties in a struct --->
<cfimage action="info" structName="anImageStruct" source="#TempImage#">
<!--- write the image out to the browser --->
<p>Original Image (<cfoutput>#anImageStruct.width# X #anImageStruct.height#</cfoutput>)<br/>
<cfimage action="WriteToBrowser" source="#TempImage#"></p>
<!--- set the resize params --->
<cfset ImageSetAntialiasing(TempImage,"on") />
<cfset targetWidth = 100>
<cfset ratioDivider = anImageStruct.width / targetWidth>
<cfset width = anImageStruct.width / ratioDivider>
<cfset height = NumberFormat(anImageStruct.height / ratioDivider)>
<!--- perform the resize --->
<cfimage action="resize"
height="#height#"
width="#width#"
source="#TempImage#"
name="ScaledImage"
quality="1"
destination="#cffile.ServerDirectory#/thumb_#cffile.ServerFile#"
overwrite="true"/>
<!--- write the image out to the browser --->
<p>Resized Image (<cfoutput>#width# X #height#</cfoutput>)<br/>
<cfimage action="WriteToBrowser" source="#ScaledImage#"></p>
<cfelse>
<!--- the form to upload an image --->
<cfform action="#cgi.script_name#"
method="post"
enctype="multipart/form-data"
name="theForm">
<cfinput type="file" name="FileUpload">
<cfinput name="submit" type="submit" value="Submit">
</cfform>
</cfif>
Here's the output:

A couple of things to note here. I have tried and tried to get the cfimage tag to overwrite an image that already exists with no success. The workaround seems to be to just name the image something else, I've added thumb_ as a prefix to any thumbnail images. Secondly, you may want to capture which file types you are willing to accept. CFImage is limited to certain image formats that vary from OS to OS. You can output the file types your system can handle by dumping the getReadableImageFormats() function.
Widget Outage - Widgets Back Online
Coldfusion, twitter, Flex, Widgetsx10hosting.com, the host where my widgets were being stored was doing server updates. I've moved the widgets to the lanctr.com domain. They are all back online again, but the wizards will need to be re-run to get the object and embed tags with the new domain.
Also, I had to remove the 2 minute Twitter widget refresh. This morning I quickly hit the 100 requests per hour limit on my twitter proxy. I'm looking into a solution for this and will have the widget updated when the solution is in hand.
Thanks for your patience!
ColdFusion Book for Coda
Coldfusion, Coda, Mac OS XWith the 1.5 release of Coda, an OS X IDE, you can now create your own books. I've created one that uses the CF liveDocs.
Grab it here: learncf.lanctr.com/coda_books/CF%20LiveDocs.zip
To use the book, simply unzip the files into "<your home folder>/Library/Application Support/Coda/Books". Then fire up Coda and you should see the new CF Book in the Books view!
To learn more about Coda, which supports Subversion natively now by-the-way, check out www.panic.com/coda If you develop on a Mac I highly reccommend you give Coda a try.
Badge / Widget Wizards
Coldfusion, FlexI've added two more badge wizards.
A weather widget, and an auto updating webcam widget.
Check them out here: http://learncf.lanctr.com/badges/index.cfm
Or you can click the link at the top labeled "Flex Badge Wizards"
Enjoy!
Twitter Badge Wizard
Coldfusion, twitter, FlexI've created a Twitter badge wizard. It generates the object and embed needed to display your own twitter feed.
Here's the link: learncf.lanctr.com/badges/twitterbadge.cfm
Enjoy!
Twitter Badge - How I Did It
Coldfusion, twitter, FlexLet me start by saying that twitter.com's crossdomain.xml does not allow for flash / flex clients to read from their RSS feeds unless they are within the same domain, highly inconvenient. For that reason I created a proxy to twitter on one of my domains using ColdFusion to read and relay the RSS feed.
<cfif isDefined("twitterID")>
<cfset twitterFeedURL = "http://twitter.com/statuses/user_timeline/#twitterID#.rss">
<cfhttp url="#twitterFeedURL#" method="GET"/>
<cfxml variable="theFeedXML">
<cfoutput>#XMLParse(cfhttp.fileContent)#</cfoutput>
</cfxml>
<cfheader name="Content-Type" value="text/xml">
<cfoutput>#theFeedXML#</cfoutput>
</cfif>
This takes a Twitter ID and reads the feed on twitter.com, stores it in an XML variable, sets the document header Content-Type to text/xml, then outputs the XML variable's contents, the related RSS feed for the twitter ID.
For my example I am going to be using my twitterproxy.cfm page as my proxy, but because of twitter's refresh interval limits, you should use a proxy of your own. Yahoo Pipes looked promising, but they are currently fighting with the refresh interval limits like everyone else.
Ok, let's jump into the Flex code.
Here is how I have my source directory setup.

First we need to setup the visual components of the badge.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="doIt()"
paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0" color="#FFFFFF"
themeColor="#00FF12" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#676767, #676767]"
horizontalAlign="center" verticalAlign="middle">
<mx:Script source="as/main.as" />
<mx:HTTPService id="twitterService" url="{twitterFeedURL}"
resultFormat="e4x" result="twitterServiceHandler(event);" fault="twitterFaultHandler(event);"/>
<mx:Panel id="twitterPanel" width="170" height="153" layout="absolute"
paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0" color="#FFFFFF" title="Twitter / Loading...">
<mx:TextArea width="100%" height="100%" color="#000000"
backgroundColor="#FFFFFF" editable="false" wordWrap="true" id="twitterTA"/>
<mx:SWFLoader x="0" y="0" width="100%" height="100%" id="theLoader" name="theLoader" source="{loadingSWF}"/>
</mx:Panel>
</mx:Application>
The interface is pretty straight forward. I used a panel for my main container. The panel contains the textArea we'll use to display the feed and a SWFloader that displays a "loading" animation. Above the panel is the HTTPService component used to get the feed from my twitter proxy. Lastly, above the HTTPService component is the Script component, who's source points to the main.as actionscript file in the assets directory.
In the main.as file I've imported mx.rpc.events.FaultEvent and max.rpc.events.ResultEvent to handle both result and fault events from the HTTPService.
import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent;
Next I've defined the variables I want available to all methods in the script.
[Bindable] private var twitterFeed:XML; [Bindable] private var twitterRSSID:String; [Bindable] private var twitterFeedURL:String; [Bindable] private var twitterName:String; [Bindable] private var twitterLink:String; private var twitterInterval:int;
I then embeded my "loading" animation SWF.
[Embed(source="assets/flash/spinning ring.swf")] [Bindable] private var loadingSWF:Class;
Finally, I declared a namespace to use for reading the RSS feed and set the script to use the new namespace.
private namespace atom = "http://www.w3.org/2005/Atom"; use namespace atom;
In main.mxml's Appllication component I am calling the doIt() method from the creationComplete listener. This method reads any data being passed in through the HTML document via the FlashVars object. It then sets up the initial variable values and calls the getTwitterFeed method and the twitterRefreshInterval method.
private function doIt():void{
twitterRSSID = Application.application.parameters.twitterID;
if (twitterRSSID == null) {
twitterRSSID = "9813122";
}
twitterFeedURL = "http://learncf.lanctr.com/twitterproxy.cfm?twitterID=" + twitterRSSID;
getTwitterFeed();
twitterRefreshInterval();
}
The getTwitterFeed method only contains a single line. In it we invoke the HTTPService.
private function getTwitterFeed():void {
twitterService.send();
}
The result handler for the HTTPService is triggered when data is received from my twitter proxy. twitterServiceHandler, the result handler for the HTTPService, stores the returned XML in an XML datatyped variable. I set the panel's title to the value of the title node from twitterFeed. I also set the link to the user's twitter profile in the twitterLink variable, I get the URL from the link node in twitterFeed. Next I created a RegEx to scrape out the user's twitter name from the title since the feed doesn't explicitly specify this value. Following that, the first item node in the XML feed is passed through my URLsToLinks method to replace any URLs with clickable links and to replace profile names with clickable profile names. For instance, @stevegood is changed into a link that will point to the profile of stevegood. Lastly, if the "loading" animation exists we remove it from the panel.
private function twitterServiceHandler(event:ResultEvent):void {
twitterFeed = event.result as XML;
twitterPanel.title = twitterFeed.channel.title;
twitterLink = twitterFeed.channel.link;
var reString:String = "Twitter\\s/\\s";
var reObject:RegExp = new RegExp(reString,"ig");
twitterName = twitterPanel.title.replace(reObject,'');
twitterTA.htmlText = URLsToLinks(twitterFeed.channel.item[0].description);
var loaderExists:DisplayObject = twitterPanel.getChildByName("theLoader");
if (loaderExists) {
twitterPanel.removeChild(theLoader);
}
}
The fault handler for the HTTPService is pretty straight forward. If there is a fault it removes the "loading" animation, if it exists, changes the panel's title and textArea's htmlText to reflect that there was an error.
private function twitterFaultHandler(event:FaultEvent):void {
var loaderExists:DisplayObject = twitterPanel.getChildByName("theLoader");
if (loaderExists) {
twitterPanel.removeChild(theLoader);
}
twitterPanel.title = "Twitter / Error";
twitterTA.htmlText = "An error has occurred and the feed cannot be shown. Try again later.";
}
One of the reasons I set out to build my own twitter badge was because I didn't like that the official badge didn't auto update. To make mine autoupdate I created a method that sets an interval of 2 minutes, and at the end of each interval it calls the getTwitterFeed method, which retrieves the RSS feed from my proxy.
private function twitterRefreshInterval(delay:int = 120000):void {
twitterInterval = setInterval(getTwitterFeed, delay);
}
And finally, here is the URLsToLinks method. It uses a couple of RegEx expressions to parse and replace matching strings to create the clickable links I mentioned previously, then returns the formatted string.
private function URLsToLinks(theString:String):String {
// define the RegEx strings
var URLRE:String = "(https?)://([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+([a-zA-Z]{2,9})(:\\d{1,4})?([-\\w/#~:.?+=&%@~]*)";
var twitterRE:String = "(?<![\\w\\.])(?<=@)([-\\w]*)(?![\\w\\.])";
// Create the RegEx objects
var urlPattern:RegExp = new RegExp(URLRE,"ig");
var twitterPattern:RegExp = new RegExp(twitterRE,"ig");
var twitterNamePattern:RegExp = new RegExp(twitterName,"ig");
// replace text in the string that matches the RegEx objects
var result:String = theString.replace(urlPattern,'<a href="$&" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
result = result.replace(twitterPattern,'<a href="http://twitter.com/$&" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
result = result.replace(twitterNamePattern,'<a href="' + twitterLink + '" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
// return the formatted string
return result;
}
Here is the complete main.as file.
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
[Bindable] private var twitterFeed:XML;
[Bindable] private var twitterRSSID:String;
[Bindable] private var twitterFeedURL:String;
[Bindable] private var twitterName:String;
[Bindable] private var twitterLink:String;
private var twitterInterval:int;
[Embed(source="assets/flash/spinning ring.swf")]
[Bindable] private var loadingSWF:Class;
private namespace atom = "http://www.w3.org/2005/Atom";
use namespace atom;
private function doIt():void{
twitterRSSID = Application.application.parameters.twitterID;
if (twitterRSSID == null) {
twitterRSSID = "9813122";
}
twitterFeedURL = "http://learncf.lanctr.com/twitterproxy.cfm?twitterID=" + twitterRSSID;
getTwitterFeed();
twitterRefreshInterval();
}
private function getTwitterFeed():void {
twitterService.send();
}
private function twitterServiceHandler(event:ResultEvent):void {
twitterFeed = event.result as XML;
twitterPanel.title = twitterFeed.channel.title;
twitterLink = twitterFeed.channel.link;
var reString:String = "Twitter\\s/\\s";
var reObject:RegExp = new RegExp(reString,"ig");
twitterName = twitterPanel.title.replace(reObject,'');
twitterTA.htmlText = URLsToLinks(twitterFeed.channel.item[0].description);
var loaderExists:DisplayObject = twitterPanel.getChildByName("theLoader");
if (loaderExists) {
twitterPanel.removeChild(theLoader);
}
}
private function twitterFaultHandler(event:FaultEvent):void {
var loaderExists:DisplayObject = twitterPanel.getChildByName("theLoader");
if (loaderExists) {
twitterPanel.removeChild(theLoader);
}
twitterPanel.title = "Twitter / Error";
twitterTA.htmlText = "An error has occurred and the feed cannot be shown. Try again later.";
}
private function twitterRefreshInterval(delay:int = 120000):void {
twitterInterval = setInterval(getTwitterFeed, delay);
}
private function URLsToLinks(theString:String):String {
// define the RegEx strings
var URLRE:String = "(https?)://([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+([a-zA-Z]{2,9})(:\\d{1,4})?([-\\w/#~:.?+=&%@~]*)";
var twitterRE:String = "(?<![\\w\\.])(?<=@)([-\\w]*)(?![\\w\\.])";
// Create the RegEx objects
var urlPattern:RegExp = new RegExp(URLRE,"ig");
var twitterPattern:RegExp = new RegExp(twitterRE,"ig");
var twitterNamePattern:RegExp = new RegExp(twitterName,"ig");
// replace text in the string that matches the RegEx objects
var result:String = theString.replace(urlPattern,'<a href="$&" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
result = result.replace(twitterPattern,'<a href="http://twitter.com/$&" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
result = result.replace(twitterNamePattern,'<a href="' + twitterLink + '" target="_blank"><font color="#0000FF"><u>$&</u></font></a>');
// return the formatted string
return result;
}
You can view an example of the badge working here: http://learncf.lanctr.com/badges/twitterbadge.cfm
**Edit: I removed the source download link since I no longer have an account at x10hosting. You should be able to use the post as a source reference though.





Loading....