PDA

View Full Version : cfimage & cffile - optimze image rendering in three steps



JonC
June 29th, 2011, 01:53 PM
USE: When full size images are required, re-sized images need to be used for displaying smaller images or thumbnails and the application needs to perform at optimal speed for displaying images in a browser.

KEY POINTS:

Except for during development cfimage "action="writeToBrowser" should not be used to display images.
Use CFIMAGE to resize images ONCE, if possible during upload but if page timeouts make this impossible break up the task by using a CFC to check and re-size images as needed.


SUMMARY:
Those sites that display many images often times also upload many photos via form or via FTP and need to display both the FULL size images and smaller images for thumb nails or (small, med, large) optional sizes. The process of uploading images using CFFile can impose time constraints specifically for large files, or if the coldfusion page timeouts are set lower than is possible for large file upload and re-size jobs. To overcome this issue we can write a simple CFC for resizing the images after the upload is complete and the page is run for the first time. This will be ideal for either form based upload or FTP upload making this solution very versatile.

Step 1 - Create the CFC for re-sizing and writing images to disk.


Create file "GetResizedImage.cfc" in the directory with the CFM files that display images.
Use the code below for the contents of this file and modify as needed.



<cfcomponent>
<cffunction name="GetImage" hint="Re-sizes images for display in album">
<!--- Set the image path where photos exist --->
<cfset imgpath = "imgdir/"/>
<!--- Set the domain path, allows reuse resized images on other sites --->
<cfset domain = "domain.com"/>
<!--- Re-writes image extension if for alternates of JPG, and adds _resized to differentiate from fullsize images --->
<cfset rfile= "#REReplace("#img#",".(jpg|JPG|JPEG|jpeg)","_resized.jpg")#">
<!--- Checks if file is already resized --->
<cfif FileExists("d:\home\#domain#\wwwroot\" &"#imgpath#" & "#rfile#")>
<cfset myImage="http://#domain#/#imgpath##rfile#">
<cfelse>
<!--- Resizes image if it has not been done already --->
<cfset myImage=ImageNew(URLDecode("d:\home\#domain#\wwwroot\" & "#imgpath#" & "#img#"))>
<cfset ImageResize(myImage,"175","175","highestPerformance")>
<!--- Saves image, and to eliminate problems with url friendly encoding when getting our images re-replace %20 with no-space --->
<cfimage source="#myImage#" action="write" overwrite=true destination="d:\home\#domain#\wwwroot\#imgpath##REReplace("#rfile#","%20"," ","ALL")#">
<!--- Set the new path for the image for browser output --->
<cfset myImage="http://#domain#/#imgpath##rfile#">
</cfif>
<!--- Return the image variable --->
<cfreturn myImage>
</cffunction>
</cfcomponent>

Step 2 - Invoke the CFC


<!--- Generate image name from query --->
<cfoutput query="MyEvent">
<!--- Invoke CFC to check if resized image exists, if not resize and output URL for resized image --->
<cfinvoke component="GetResizedImage"
<!--- Declare what part of the CFC handles checking / getting the image --->
method="GetImage"
<!--- Declare variable that will pass back the new image name --->
returnvariable="myImage">
<cfinvokeargument name="img" value="#event.Pic#"/>
</cfinvoke>
<!--- Display re-sized image --->
<img src="#myImage#" alt="" />
</cfoutput>

Step 3 - Test
The proposed solution cut page load times from 20+ seconds to below one second after the first page load. During the FIRST or FIRST few time the page loads all the re-sizing will be done.

Question: Checking if a file exists each time the page loads is excessive.
Answer: We agree but it's much better than resizing every image each time the page loads.