Isn't all code in existence based off of code originally written by Ben Nadel?
.:.:.:.:.:.:.:.:.:.:.:.:.:. Bobby Hartsfield http://acoderslife.com http://cf4em.com -----Original Message----- From: Eric Roberts [mailto:ow...@threeravensconsulting.com] Sent: Tuesday, April 19, 2011 11:26 AM To: cf-talk Subject: RE: Creating COM object - troubleshooting Here are the cfcs we developed based off of code originally developed by ben Nadel...some of the modification ideas were based off another site as well and I am drawing a complete blank, at the moment, who that blogger was...so if you remember the convo we had, please pop up ;-) Banner.cfc has some of the functions in imageUtils...tweaked a bit so as to work abit more efficiently. Some of the simpler functions can be replicated using the cfimage tag directly. <!---Begin ImageUtils.cfc---> <!--- Modified code developed by Eric Roberts based off of code originally developed by Ben Nadel ---> <cfcomponent output="false" hint="Image utility functions that abstract out complex ColdFusion image manipulation processes."> <cffunction name="Init" access="public" returntype="any" output="false" hint="Returns an initialized component."> <!--- Return This reference. ---> <cfreturn THIS /> </cffunction> <!--- Function: aspectCrop Author: Emmet McGovern http://www.illequipped.com/blog em...@fullcitymedia.com 2/29/2008 - Leap Day! ---> <cffunction name="aspectCrop" access="public" returntype="any" output="false" hint=""> <!--- Define arguments. ---> <cfargument name="image" type="any" required="true" hint="The ColdFusion image object or path to an image file." /> <cfargument name="cropwidth" type="numeric" required="true" hint="The pixel width of the final cropped image" /> <cfargument name="cropheight" type="numeric" required="true" hint="The pixel height of the final cropped image" /> <cfargument name="position" type="string" required="true" default="center" hint="The y origin of the crop area." /> <!--- Define local variables. ---> <cfset var nPercent = "" /> <cfset var wPercent = "" /> <cfset var hPercent = "" /> <cfset var px = "" /> <cfset var ycrop = "" /> <cfset var xcrop = "" /> <!--- If not image, assume path. ---> <cfif ( (NOT isImage(arguments.image)) AND (NOT isImageFile(arguments.image)) )> <cfthrow message="The value passed to aspectCrop was not an image." /> </cfif> <!--- If we were given a path to an image, read the image into a ColdFusion image object. ---> <cfif isImageFile(arguments.image)> <cfset arguments.image = imageRead(arguments.image) /> </cfif> <!--- Resize image without going over crop dimensions---> <cfset wPercent = arguments.cropwidth / arguments.image.width> <cfset hPercent = arguments.cropheight / arguments.image.height> <cfif wPercent gt hPercent> <cfset nPercent = wPercent> <cfset px = arguments.image.width * nPercent + 1> <cfset ycrop = ((arguments.image.height - arguments.cropheight)/2)> <cfset imageResize(arguments.image,px,"") /> <cfelse> <cfset nPercent = hPercent> <cfset px = arguments.image.height * nPercent + 1> <cfset xcrop = ((arguments.image.width - arguments.cropwidth)/2)> <cfset imageResize(arguments.image,"",px) /> </cfif> <!--- Set the xy offset for cropping, if not provided defaults to center ---> <cfif listfindnocase("topleft,left,bottomleft", arguments.position)> <cfset xcrop = 0> <cfelseif listfindnocase("topcenter,center,bottomcenter", arguments.position)> <cfset xcrop = (arguments.image.width - arguments.cropwidth)/2> <cfelseif listfindnocase("topright,right,bottomright", arguments.position)> <cfset xcrop = arguments.image.width - arguments.cropwidth> <cfelse> <cfset xcrop = (arguments.image.width - arguments.cropwidth)/2> </cfif> <cfif listfindnocase("topleft,topcenter,topright", arguments.position)> <cfset ycrop = 0> <cfelseif listfindnocase("left,center,right", arguments.position)> <cfset ycrop = (arguments.image.height - arguments.cropheight)/2> <cfelseif listfindnocase("bottomleft,bottomcenter,bottomright", arguments.position)> <cfset ycrop = arguments.image.height - arguments.cropheight> <cfelse> <cfset ycrop = (arguments.image.height - arguments.cropheight)/2> </cfif> <!--- Return new cropped image. ---> <cfset ImageCrop(arguments.image,xcrop,ycrop,arguments.cropwidth,arguments.cropheig ht)> <cfreturn arguments.image> </cffunction> <cffunction name="img_convert_gif" access="public" output="false" returntype="Any"> <cfargument name = "img_source" type = "string" required="true"> <cfargument name = "img_destination" type = "string" required="true"> <cfimage action = "convert" source = "#img_source#" destination = "#img_destination#" overwrite = "true" > </cffunction> <cffunction name="img_read_attributes" access="public" output="true" returntype="Any" hint="get attributes of image file: Required parameter is the path to source and you can optionally add a comma delimited list of file types allowed to determine the image is valid."> <!--- read the image from the path and return the with and height ---> <cfargument name = "img_source" type = "string" required="true"> <cfargument name="file_types" type="string" required="false"> <cfparam name="file_types" default=""> <cfimage name = "mainImage" source = "#img_source#" > <cfset img=structNew()> <cfset img.file_types=#file_types#> <cfset img.height=ImageGetHeight(mainImage)> <cfset img.width=ImageGetWidth(mainImage)> <cfif img.file_types neq ""> <cfset img_type= listgetat("#img_source#",2,".")> <cfif img_type is "jpeg"> <cfset img_type="jpg"> </cfif> <cfloop list="#img.file_types#" index="ft"> <cfif #trim(ft)# eq "#trim(img_type)#"> <cfset img.valid_image_type=true> <cfset img.format="#ft#"> <cfbreak> <cfelse> <cfset img.valid_image_type=false> <cfset img.format="Invalid Image Format"> </cfif> </cfloop> <cfset img.isValidImage=isImageFile('#img_source#')> <cfif img.isValidImage is true and img.valid_image_type is true> <cfset img.valid_image= true> <cfelse> <cfset img.valid_image= false> </cfif> </cfif> <!--- <cfset img.height= ImageGetHeight(mainImage)> <cfset img.width = ImageGetWidth(mainImage)> ---> <!--image.filesize=GetFileInfo(#img_source#).size--> <cfset img.filePath="#img_source#"> <cfset img.filesize=GetFileInfo(#img_source#).size> <cfif img.width GE img.height> <cfset img.orientation = 'L'> <cfelse> <cfset img.orientation = 'P'> </cfif> <cfreturn img> </cffunction> <cffunction name="img_resize" access="public" output="true" hint="all parameters are required. To scale to height or width, set one to zero and the other to the desired value."> <!--- need the following defined final width and height where the image is and where the image should be resized to source file name and final file name ---> <cfargument name = "img_resize_width" type = "numeric" required="true"> <cfargument name = "img_resize_height" type = "numeric" required="true"> <cfargument name = "path_source" type = "string" required="true"> <cfargument name = "path_dest" type = "string" required="true"> <cfargument name = "img_source_name" type = "string" required="true"> <cfargument name = "img_dest_name" type = "string" required="true"> <cfif img_resize_width is 0> <cfset img_resize_width=''> </cfif> <cfif img_resize_height is 0> <cfset img_resize_height=''> </cfif> <cfif FileExists("#path_source#/#img_source_name#")> <cfimage source = "#path_source#/#img_source_name#" name="my_image"> <cfset ImageSetAntialiasing(my_image,"on")> <cfset imageScaletoFit(my_image,'#img_resize_width#','#img_resize_height#')> <cfset ImageWrite(my_image,"#path_dest#\#img_dest_name#")> <!--- <cfelse> Error Image could not be found. NO Image cropped. <cferror type = "REQUEST" template = "template_path" > ---> </cfif> </cffunction> <cffunction name="img_crop" access="public" output="true"> <!--- need the following where the image is located and where the image should be saved source file name and destination file name Maximum are the cropping size for the width and height first reduce the width or height for proportionality to fit in the area then crop the image the minimum width or height for the rest of the area to be cropped out ---> <cfargument name = "img_crop_width" type = "numeric" required="true"> <cfargument name = "img_crop_height" type = "numeric" required="true"> <cfargument name = "path_source" type = "string" required="true"> <cfargument name = "path_dest" type = "string" required="true"> <cfargument name = "img_source_name" type = "string" required="true"> <cfargument name = "img_dest_name" type = "string" required="true"> <cfif FileExists("#path_source#/#img_source_name#")> <cfimage source = "#path_source#/#img_source_name#" name="my_image"> <cfset img_height_source = #int(ImageGetHeight(my_image))#> <cfset img_width_source = #int(ImageGetWidth(my_image))#> <cfset img_ratio = int(#img_width_source#/#img_height_source#)> <cfset dest_ratio = int(#img_crop_width#/#img_crop_height#)> <cfset ImageSetAntialiasing(my_image,"on")> <!--- <cfset imageScaletoFit(my_image,#img_crop_width#,#img_crop_height#)> ---> <!--- crop image depending on the orientation of the image ---> <cfif img_ratio GE #dest_ratio#> <cfset imageScaletoFit(my_image,1000000,#img_crop_height#)> <cfelse> <cfset imageScaletoFit(my_image,#img_crop_width#,1000000)> </cfif> <cfset ImageCrop(my_image, 0, 0, #img_crop_width#, #img_crop_height#)> <cfset ImageWrite(my_image,"#path_dest#\#img_dest_name#")> <!--- <cfelse> Error Image could not be found. NO Image cropped. <cferror type = "REQUEST" template = "template_path" > ---> </cfif> </cffunction> <cffunction name="textover_solid_bg" access="public" output="true"> <!--- need the following font font size text color bg color border color destination save image as company.gif and appropriate fh directory ---> <cfargument name = "img_height" type="any" required="false" default = "400"> <cfargument name = "img_width" type="any" required="false" default = "300"s> <cfargument name = "box_color" type="any" required="false" default = "000000"> <cfargument name = "border_color" type="any" required="false" default = "000000"> <cfargument name = "text_color" type="any" required="false" default = "ffffff"> <cfargument name = "text_font" type="any" required="false" default = "Arial"> <cfargument name = "text_size" type="any" required="false" default = "18"> <cfargument name = "text_style" type="any" required="false" default = "bold"> <cfargument name = "text_body" type="any" required="false" default = "sample text"> <cfargument name = "dest_filename" type="any" required="true"> <cfargument name = "dest_path" type="any" required="true"> <!--- Create the image utils object. ---> <cfset objImageUtils = CreateObject( "component", "imageUtils" ).Init() /> <!--- Read in image. <cfimage action="read" source="cute_blonde.jpg" name="objImage" /> ---> <cfset objImage=ImageNew("",#img_height#,#img_width#, "rgb","#box_color#")> <cfset obj_image_width_full = #int(ImageGetWidth(objimage))#> <cfset obj_image_height_full = #int(ImageGetHeight(objimage))#> <cfset obj_image_width = #obj_image_width_full# * 0.8> <!--- Create text properties. ---> <cfset objTextProperties = { Size = "#text_size#", Font = "#text_font#", Style = "#text_style#", LineHeight = "#text_size#", TextAlign = "center" } /> <!--- Draw the text area. ---> <cfset objImageUtils.DrawTextArea( objImage, "#text_body#", 20, #obj_image_height_full#, #obj_image_width#, objTextProperties ) /> <!--- Write to browser. <cfimage action="writetobrowser" source="#objImage#" /> ---> <!--- save it to the server ---> <cfset ImageWrite(objImage,"#dest_path##dest_filename#")> </cffunction> <!--- no longer used ---> <!--- <cffunction name="text_overlay" access="public" output="true"> <!--- need the following font font size text color bg color border color destination save image as company.gif and appropriate fh directory ---> <cfargument name = "img_height" type="numeric" required="true" > <cfargument name = "img_width" type="numeric" required="true"> <cfargument name = "box_color" type="any" required="false" default = "000000"> <cfargument name = "border_color" type="any" required="false" default = "000000"> <cfargument name = "text_color" type="any" required="false" default = "ffffff"> <cfargument name = "text_font" type="any" required="false" default = "AlgerianD"> <cfargument name = "text_size" type="any" required="false" default = "24"> <!---This arguments is for Font Weight ---> <cfargument name = "text_style" type="any" required="false" default = "bold"> <cfargument name = "text" type="any" required="false" default = "sample text"> <cfargument name = "dest_path" type="any" required="true"> <cfargument name = "dest_filename" type="any" required="true"> <!---offsets image width to account for font size ---> <cfset img_width=img_width+5> <cfset img_height=img_height+5> <cfset mainImage=ImageNew("",#img_width#,#img_height#, "rgb","#box_color#")> <cfset attr=StructNew()> <cfset attr.font="#trim(text_font)#"> <cfscript> attr.size=Javacast("string", text_size); </cfscript> <cfset attr.style="#text_style#"> <cfset attr.strikethrough="no"> <cfset attr.underline="no"> <cfset ImageSetDrawingColor(mainImage,"#text_color#")> <cfset ImageSetAntialiasing(mainImage, "on")> <!--- Determine font offset for vertical placement of text, horizontal placement is based on font size ---> <!--- <cfif attr.size gte 12 and attr.size lt 20> <cfset variables.font_offset=1> <cfelseif attr.size gte 20 and attr.size lt 40> <cfset variables.font_offset=5> <cfelseif attr.size gte 40 and attr.size lt 60> <cfset variables.font_offset=10> <cfelseif attr.size gte 60 and attr.size lt 80> <cfset variables.font_offset=15> <cfelseif attr.size gte 80> <cfset variables.font_offset=20> <cfelseif attr.size lt 12> <cfset variables.font_offset=0> </cfif> ---> <!---offsets horizontal placement to better center image---> <!--- <cfswitch expression="#attr.size#"> <cfcase value="18"> <cfset variables.fontheight_offset=attr.size-5> </cfcase> <cfcase value="22"> <cfset variables.fontheight_offset=attr.size-6> </cfcase> <cfcase value="24"> <cfset variables.fontheight_offset=attr.size-7> </cfcase> <cfcase value="28"> <cfset variables.fontheight_offset=attr.size-8> </cfcase> <cfcase value="30"> <cfset variables.fontheight_offset=attr.size-9> </cfcase> <cfdefaultcase> <cfset variables.fontheight_offset=attr.size-4> </cfdefaultcase> </cfswitch> ---> <cfset variables.font_offset = (img_width/2 -arguments.img_width/2)> <cfset variables.fontheight_offset = (arguments.img_height/2 +img_height/2)> <!--- <cfset ImageDrawText(mainImage,text,img_width,img_height,attr)> ---> <cfset ImageDrawText(mainImage,text,#variables.font_offset#,#variables.fontheight_o ffset#,attr)> <!--- <cfset ImageDrawText(mainImage,text,xLine,topY,fontline)> ---> <cfimage action = "write" source = "#mainImage#" destination = "#dest_path#\#dest_filename#" overwrite = "yes" > </cffunction> ---> <cffunction name="verify_image" access="public" output="true" returntype="Any"> <!--- read the image from the path and return the with and height ---> <cfargument name = "img_source" type = "string" required="true"> <cfset verified_image=isImageFile("#img_source#")> <return verifed_image> </cffunction> <cffunction name="CalculateGradient" access="public" returntype="array" output="false" hint="Given a From and To normalized color structure (as defined by the NormalizeColor() function) that contain Red, Green, Blue, and Alpha keys, it will return the equivalent structs for each step of the gradient."> <!--- Define arguments. ---> <cfargument name="FromColor" type="struct" required="true" hint="A normalized color struct."/> <cfargument name="ToColor" type="struct" required="true" hint="A normalized color struct."/> <cfargument name="Steps" type="numeric" required="true" hint="The number of steps overwhich to calculate the gradient." /> <!--- Define the local scope. ---> <cfset var LOCAL = {} /> <!--- Find the differences between the two and from colors. We will getting this by finding the difference of each color chanel in RGB format. ---> <cfset LOCAL.RedDelta = (ARGUMENTS.ToColor.Red - ARGUMENTS.FromColor.Red) /> <cfset LOCAL.GreenDelta = (ARGUMENTS.ToColor.Green - ARGUMENTS.FromColor.Green) /> <cfset LOCAL.BlueDelta = (ARGUMENTS.ToColor.Blue - ARGUMENTS.FromColor.Blue) /> <cfset LOCAL.AlphaDelta = (ARGUMENTS.ToColor.Alpha - ARGUMENTS.FromColor.Alpha) /> <!--- Based on the number of steps that we want to define the gradient, find the step for each color delta. ---> <cfset LOCAL.RedStep = (LOCAL.RedDelta / ARGUMENTS.Steps) /> <cfset LOCAL.GreenStep = (LOCAL.GreenDelta / ARGUMENTS.Steps) /> <cfset LOCAL.BlueStep = (LOCAL.BlueDelta / ARGUMENTS.Steps) /> <cfset LOCAL.AlphaStep = (LOCAL.AlphaDelta / ARGUMENTS.Steps) /> <!--- Create an array to hold the color steps. ---> <cfset LOCAL.Gradient = [] /> <!--- Create a start color. ---> <cfset LOCAL.Color = StructCopy( ARGUMENTS.FromColor ) /> <!--- Loop over color differences to calculate. ---> <cfloop index="LOCAL.StepIndex" from="1" to="#ARGUMENTS.Steps#" step="1"> <!--- Store the gradient step. ---> <cfset ArrayAppend( LOCAL.Gradient, StructCopy( LOCAL.Color ) ) /> <!--- Increment color. In order to make sure that the gradient steps get used appropriatly, add the steps directly the FROM color rather than to the previous color index. This will prevent the Fix() function from stopping our gradient if the increment is too small. ---> <cfset LOCAL.Color.Red = Fix( ARGUMENTS.FromColor.Red + (LOCAL.RedStep * LOCAL.StepIndex) ) /> <cfset LOCAL.Color.Green = Fix( ARGUMENTS.FromColor.Green + (LOCAL.GreenStep * LOCAL.StepIndex) ) /> <cfset LOCAL.Color.Blue = Fix( ARGUMENTS.FromColor.Blue + (LOCAL.BlueStep * LOCAL.StepIndex) ) /> <cfset LOCAL.Color.Alpha = Fix( ARGUMENTS.FromColor.Alpha + (LOCAL.AlphaStep * LOCAL.StepIndex) ) /> </cfloop> <!--- Return gradient array. ---> <cfreturn LOCAL.Gradient /> </cffunction> <cffunction name="ColorsAreEqual" access="public" returntype="boolean" output="false" hint="Determines if the given two *normalized* colors (as defined by NormalizeColor() function) are equal in color given the tolerance. By default, all transparent pixels are equal."> <!--- Define arguments. ---> <cfargument name="ColorOne" type="struct" required="true" hint="A normalized color struct." /> <cfargument name="ColorTwo" type="struct" required="true" hint="A normalized color struct." /> <cfargument name="Tolerance" type="numeric" required="false" default="0" hint="The tolerance between the color channels when determining if the colors are equal (max possible delta in channel value)." /> <cfargument name="AlphaPrecedence" type="boolean" required="false" default="true" hint="Flags whether or not the alpha channel takes precedence over the color channels." /> <!--- Define the local scope. ---> <cfset var LOCAL = {} /> <!--- Check to see if alpha has precedence and both pixels are transparent. ---> <cfif ( ARGUMENTS.AlphaPrecedence AND (ARGUMENTS.ColorOne.Alpha LTE ARGUMENTS.Tolerance) AND (ARGUMENTS.ColorTwo.Alpha LTE ARGUMENTS.Tolerance) )> <!--- Both pixels are transparent and we have defined those as being equal. ---> <cfreturn true /> </cfif> <!--- Check to see if these pixles are within the tolerance of each other. ---> <cfreturn ( (Abs( ARGUMENTS.ColorOne.Red - ARGUMENTS.ColorTwo.Red ) LTE ARGUMENTS.Tolerance) AND (Abs( ARGUMENTS.ColorOne.Green - ARGUMENTS.ColorTwo.Green ) LTE ARGUMENTS.Tolerance) AND (Abs( ARGUMENTS.ColorOne.Blue - ARGUMENTS.ColorTwo.Blue ) LTE ARGUMENTS.Tolerance) AND (Abs( ARGUMENTS.ColorOne.Alpha - ARGUMENTS.ColorTwo.Alpha ) LTE ARGUMENTS.Tolerance) ) /> </cffunction> <cffunction name="CreateGradient" access="public" returntype="any" output="false" hint="Creates a gradient rectangle to be used with other graphics."> <!--- Define arguments. ---> <cfargument name="FromColor" type="struct" required="true" hint="The normalized color struct from which to start our gradient." /> <cfargument name="ToColor" type="struct" required="true" hint="The normalized color struct at which to end our gradient." /> <cfargument name="GradientDirection" type="string" required="true" hint="The direction in which to darw the gradient. Possible values are TopBottom, BottomTop, LeftRight, and RightLeft." /> <cfargument name="Width" type="numeric" required="true" hint="The width of the desired rectangle." /> <cfargument name="Height" type="numeric" required="true" hint="The height of the desired rectangle." /> <!--- Define the local scope. ---> <cfset var LOCAL = {} /> <!--- Make sure that we have a valid direciton. ---> <cfif NOT ListFindNoCase( "TopBottom,BottomTop,LeftRight,RightLeft", ARGUMENTS.GradientDirection )> <!--- Inavlid gardient, default to TopBottom. ---> <cfset ARGUMENTS.GradientDirection = "TopBottom" /> </cfif> <!--- Create a new transparent gradient. It is important that it is transparent since the gradient utilizes an alpha channel. ---> <cfset LOCAL.Gradient = ImageNew( "", ARGUMENTS.Width, ARGUMENTS.Height, "argb", "" ) /> <!--- In order to figure out what steps that we need to create, we need to figure out which direction the gradient is going in. ---> <cfswitch expression="#ARGUMENTS.GradientDirection#"> <!--- For vertical gradients, use the height to define the number of steps. ---> <cfcase value="TopBottom,BottomTop" delimiters=","> <cfset LOCAL.StepCount = ARGUMENTS.Height /> </cfcase> <!--- For horizontal gradients, use the width to define the number of steps. ---> <cfcase value="LeftRight,RightLeft" delimiters=","> <cfset LOCAL.StepCount = ARGUMENTS.Width /> </cfcase> </cfswitch> <!--- Calculate the gradient using our From and To colors. This will give us all the colors in the gradient. ---> <cfset LOCAL.GradientSteps = THIS.CalculateGradient( THIS.NormalizeColor( ARGUMENTS.FromColor ), THIS.NormalizeColor( ARGUMENTS.ToColor ), LOCAL.StepCount ) /> <!--- Now that we have our gradient steps, we can start to apply our individual color steps to the blank canvas in order to create the gradient rectangle. ---> <!--- We don't want there to be too much fuziness, so turn off antialiasing. ---> <cfset ImageSetAntialiasing( LOCAL.Gradient, "off" ) /> <!--- Loop over the steps in the gradient. ---> <cfloop index="LOCAL.StepIndex" from="1" to="#LOCAL.StepCount#" step="1"> <!--- Set the current drawing color. ---> <cfset ImageSetDrawingColor( LOCAL.Gradient, ( LOCAL.GradientSteps[ LOCAL.StepIndex ].Red & "," & LOCAL.GradientSteps[ LOCAL.StepIndex ].Green & "," & LOCAL.GradientSteps[ LOCAL.StepIndex ].Blue )) /> <!--- Set the drawing transparency. When doing this, we have to be careful as we are not setting the opacity, which is actually the opposite value. An alpha channel of 255 is totally opaque, but requires a tranparency of zero. ---> <cfset ImageSetDrawingTransparency( LOCAL.Gradient, (100 - (LOCAL.GradientSteps[ LOCAL.StepIndex ].Alpha / 255 * 100)) ) /> <!--- When we actually draw the rectangle, we have to take into account the direction of the gradient to figure out where the individual step gradient will be applied. ---> <cfswitch expression="#ARGUMENTS.GradientDirection#"> <cfcase value="TopBottom"> <cfset ImageDrawRect( LOCAL.Gradient, 0, (LOCAL.StepIndex - 1), ARGUMENTS.Width, 1, true ) /> </cfcase> <cfcase value="BottomTop"> <cfset ImageDrawRect( LOCAL.Gradient, 0, (ARGUMENTS.Height - LOCAL.StepIndex), ARGUMENTS.Width, 1, true ) /> </cfcase> <cfcase value="LeftRight"> <cfset ImageDrawRect( LOCAL.Gradient, (LOCAL.StepIndex - 1), 0, 1, ARGUMENTS.Height, true ) /> </cfcase> <cfcase value="RightLeft"> <cfset ImageDrawRect( LOCAL.Gradient, (ARGUMENTS.Width - LOCAL.StepIndex), 0, 1, ARGUMENTS.Height, true ) /> </cfcase> </cfswitch> </cfloop> <!--- Return gradient rectangle. ---> <cfreturn LOCAL.Gradient /> </cffunction> <cffunction name="DrawGradientRect" access="public" returntype="any" output="false" hint="Takes an image and draws the given gradient rectangle on it."> <!--- Define arguments. ---> <cfargument name="Image" type="any" required="true" hint="The ColdFusion image object onto which we are drawing the gradient." /> <cfargument name="X" type="numeric" required="true" hint="The X coordinate at which to start drawing the rectangle." /> <cfargument name="Y" type="numeric" required="true" hint="The Y coordinate at which to start drawing the rectangle." /> <cfargument name="Width" type="numeric" required="true" hint="The width of the desired rectangle." /> <cfargument name="Height" type="numeric" required="true" hint="The height of the desired rectangle." /> <cfargument name="FromColor" type="struct" required="true" hint="The HEX, R,G,B,A list, or color struct for the start color of our gradient." /> <cfargument name="ToColor" type="struct" required="true" hint="TheHEX, R,G,B,A list, or color struct for the end color of our gradient." /> <cfargument name="GradientDirection" type="string" required="true" hint="The direction in which to darw the gradient. Possible values are TopBottom, BottomTop, LeftRight, and RightLeft." /> <!--- Define the local scope. ---> <cfset var LOCAL = {} /> <!--- Create the gradient rectangle. ---> <cfset LOCAL.Gradient = THIS.CreateGradient( THIS.NormalizeColor( ARGUMENTS.FromColor ), THIS.NormalizeColor( ARGUMENTS.ToColor ), ARGUMENTS.GradientDirection, ARGUMENTS.Width, ARGUMENTS.Height ) /> <!--- Paste the gradient onto the image. ---> <cfset ImagePaste( ARGUMENTS.Image, LOCAL.Gradient, ARGUMENTS.X, ARGUMENTS.Y ) /> <!--- Return the updated image. ---> <cfreturn ARGUMENTS.Image /> </cffunction> <!--- Author: Ben Nadel Taken from: http://www.bennadel.com/blog/977-ColdFusion-8-ImageDrawTextArea-Inspired-By- Barney-Boisvert.htm ---> <cffunction name="DrawTextArea" access="public" returntype="void" output="true" hint="Draws a text area on the given canvas."> <cfargument name="Source" type="any" required="true" hint="The image on which we are going to write the text." /> <cfargument name="Text" type="string" required="true" hint="The text value that we are going to write." /> <cfargument name="X" type="numeric" required="true" hint="The X coordinate of the start of the text." /> <cfargument name="Height" type="numeric" required="true" hint="Height of the Image" /> <cfargument name="Width" type="numeric" required="true" hint="The width of the text area in which the text should fit." /> <cfargument name="Attributes" type="struct" required="false" default="#StructNew()#" hint="The attributes of the font (including TextAlign and LineHeight)." /> <!--- Define the local scope. ---> <cfset var LOCAL = {} /> <!--- In additional the standard attributes defined above, this function allows for a few additional font attributes. Let's give them some default values. ---> <cfparam name="ARGUMENTS.Attributes.LineHeight" type="numeric" default="#(1.4 * ARGUMENTS.Attributes.Size)#" /> <cfparam name="ARGUMENTS.Attributes.TextAlign" type="string" default="left" /> <!--- Now, that we have our font-testing environment set up, it's time to start figuring out how we are gonna layout the text. To begin, we are going to take the user's text and split it up into an array of word tokens (based on single spaces). ---> <cfset LOCAL.Words = ARGUMENTS.Text.Split( JavaCast( "string", " " ) ) /> <!--- As we loop through the words, we are going to keep track of which words fit onto each line and the dimensions that that line occupies. To store this, we will use an array of Line structures. ---> <cfset LOCAL.Lines = [] /> <!--- Create the first line item. Here, the Text is the string data for the line and the Width / Height are the physical dimensions of the text. ---> <cfset LOCAL.Lines[ 1 ] = { Text = "", Width = 0, Height = 0 } /> <!--- Loop over all the words. ---> <cfloop index="LOCAL.WordIndex" from="1" to="#ArrayLen( LOCAL.Words )#" step="1"> <!--- Get a short hand to the current word. ---> <cfset LOCAL.Word = LOCAL.Words[ LOCAL.WordIndex ] /> <!--- Get a short hand to the current line. ---> <cfset LOCAL.Line = LOCAL.Lines[ ArrayLen( LOCAL.Lines ) ] /> <!--- Get the text dimensions of the current line with the addition of the next word. ---> <cfset LOCAL.Dimensions = THIS.GetTextDimensions( Trim( LOCAL.Line.Text & " " & LOCAL.Word ), StructCopy( ARGUMENTS.Attributes ) ) /> <!--- Now that we have the physical dimensions, we need to check to see if new line would be too wide for the text area. If it is too wide and there is not text on the line yet, then add it anyway as it simply is too wide for the text area. ---> <cfif ( (LOCAL.Dimensions.Width LTE ARGUMENTS.Width) OR (NOT Len( LOCAL.Line.Text )) )> <!--- The current word will fit on the current line so add it to the string data of the line. If this is NOT the first word, be sure to add a preceeding space. ---> <cfset LOCAL.Line.Text &= ( IIF( Len( LOCAL.Line.Text ), DE( " " ), DE( "" ) ) & LOCAL.Word ) /> <!--- Since the text data of this line has been updated, we need to get the updated dimensions of the line. When it comes go getting the width, we have to be careful about lines that are too wide for the text area. We never want to record any width that is larger than the text area. ---> <cfset LOCAL.Line.Width = Min( LOCAL.Dimensions.Width, ARGUMENTS.Width ) /> <!--- Get height. ---> <cfset LOCAL.Line.Height = LOCAL.Dimensions.Height /> <cfelse> <!--- Due to the dimensions of the potential line, we are going to have to move the current word to a new line. For this we must create a new line object and insert the word. ---> <!--- Get the bounds of the new line (which will be the same as the bounds of the current word). ---> <cfset LOCAL.Dimensions = THIS.GetTextDimensions( LOCAL.Word, StructCopy( ARGUMENTS.Attributes ) ) /> <!--- Create a new line object. ---> <cfset LOCAL.Line = { Text = LOCAL.Word, Width = LOCAL.Dimensions.Width, Height = LOCAL.Dimensions.Height } /> <!--- Append the new line object to our array. ---> <cfset ArrayAppend( LOCAL.Lines, LOCAL.Line ) /> </cfif> </cfloop> <cfset Arguments.Y = ( 0.5 * #HEIGHT#) - (#ArrayLen( LOCAL.Lines )#/2) * #ARGUMENTS.Attributes.lineheight# + (#ARGUMENTS.Attributes.lineheight# )> <!--- ASSERT: At this point, we have determined which text will go on which lines of our rendered text area. We also know the dimensions of each line of text. ---> <!--- Now, it's time to actually draw the text on the passed in image object. Loop over the lines array. ---> <cfloop index="LOCAL.LineIndex" from="1" to="#ArrayLen( LOCAL.Lines )#" step="1"> <!--- Get a shorthand to the current line object. ---> <cfset LOCAL.Line = LOCAL.Lines[ LOCAL.LineIndex ] /> <cfset LOCAL.Y = (( #ArrayLen(LOCAL.Lines)#/2 * #ARGUMENTS.Attributes.lineheight#) + 1/2* #ARGUMENTS.Attributes.lineheight# )> <!--- add next time of the text ---> <cfset LOCAL.Y = Local.Y + #ARGUMENTS.Attributes.lineheight# > <!--- Let's determine the X-coordinate of this <<<Additional text truncated.>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| Order the Adobe Coldfusion Anthology now! http://www.amazon.com/Adobe-Coldfusion-Anthology/dp/1430272155/?tag=houseoffusion Archive: http://www.houseoffusion.com/groups/cf-talk/message.cfm/messageid:343875 Subscription: http://www.houseoffusion.com/groups/cf-talk/subscribe.cfm Unsubscribe: http://www.houseoffusion.com/groups/cf-talk/unsubscribe.cfm