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
[email protected]
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
line of
text. This will depend on the alignment of
the text
(left, center, right).
--->
<cfswitch
expression="#ARGUMENTS.Attributes.TextAlign#">
<!--- Right aligned text. --->
<cfcase value="right">
<cfset LOCAL.X = (
ARGUMENTS.X +
ARGUMENTS.Width -
LOCAL.Line.Width
) />
</cfcase>
<!--- Center align text. --->
<<<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:343849
Subscription: http://www.houseoffusion.com/groups/cf-talk/subscribe.cfm
Unsubscribe: http://www.houseoffusion.com/groups/cf-talk/unsubscribe.cfm