Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Ray Camden and Todd Sharp

Foundeo's CFImageEffects Component For ColdFusion 8

By Ben Nadel on
Tags: ColdFusion

Foundeo.com has given me a copy of their new ColdFusion 8 component, CFImageEfects.cfc, for review. CFImageEffects has functionality to do some pretty cool things to ColdFusion 8 image objects including:

  • Drawing filled gradient rectangles.
  • Applying a reflection effect (as if the image was on a shinney, reflective surface).
  • Applying a plastic effect, giving the target image a plasticy-surface look.
  • Applying rounded corners.
  • Applying a drop shadow.

I am not sure I can see myself using all of these effects, so I thought I would pick the ones that felt most useful for my situations and give those a little exploration. In particular, I could definitely see myself using the drop shadow, the rounded corners, and the reflection affect.

To start off, I needed to create and read in a new image:

  • <!---
  • Read in the test image to which we will be
  • applying the given effects.
  • --->
  • <cfimage
  • action="read"
  • source="./girl_with_fan.jpg"
  • name="objImage"
  • />
  •  
  •  
  • <!---
  • Write image to browswer so that we can see what
  • the original looks like before we start applying
  • the CFImageEffects actions.
  • --->
  • <cfimage
  • action="writetobrowser"
  • source="#objImage#"
  • />

This writes the following image to the browser:


 
 
 

 
Girl Cooling Her Private Bits With A Fan  
 
 
 

NOTE: All of these examples are being run on HostMySite.com's beta accounts and may not be running the latest release of ColdFusion 8.

Ok, now it's time to play around with applying the effects. Before we can do that, we need to create an instance of Foundeo's new CFImageEffects ColdFusion 8 component:

  • <!---
  • Now that we have our image, let's create an instance
  • of the CFImageEffect ColdFusion component.
  • --->
  • <cfset objEffects = CreateObject(
  • "component",
  • "CFImageEffects"
  • ).Init()
  • />

This objEffects ColdFusion component instance will be used for the remainder of the code samples. For starters, let's try the drop shadow effect. The only required parameter to this function is the image itself:

  • <!---
  • Let's apply the default drop shadow. This affect
  • returns a new image object with the applied affect,
  • leaving our original untouched.
  • --->
  • <cfset objNewImage = objEffects.ApplyDropShadowEffect(
  • objImage
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get a quite pleasing drop shadow effect:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Default Drop Shadow  
 
 
 

What you can't see from my screen shot (or what might not be obvious) is that the canvas of the returned image has increased in size both vertically and horizontally in order to accommodate the drop shadow. This will happen with many of the effects that can be applied using ColdFusion 8's new image manipulation functions.

In addition to the image, ApplyDropShadowEffect() can also take the background color of the expanded canvas, the drop shadow color, the drop shadow width, and the drop shadow offset:

  • <!---
  • This time, when applying the drop shadow, let use the
  • optional parameters to really gain control over the
  • look and feel.
  • --->
  • <cfset objNewImage = objEffects.ApplyDropShadowEffect(
  • <!--- The image. --->
  • objImage,
  •  
  • <!--- Background color of the canvas. --->
  • "FFFFFF",
  •  
  • <!--- Shadow color. --->
  • "333333",
  •  
  • <!--- Shadow width. --->
  • 10,
  •  
  • <!---
  • Shadow distance. This is the offset of the shadow
  • effect from the border of the original image.
  • --->
  • 0
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get this new image:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Darker Drop Shadow  
 
 
 

With the darker shadow, it becomes more obvious where the canvas grows and does not grow. At the top-right and the bottom-left, we get a very hard-edged truncation of the drop shadow. To help counter this issue, we can add an offset to the drop shadow. Running the above code again, but this time with an offset of 10 (last argument in function invocation), we get a much more pleasing drop shadow:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Darker Drop Shadow With Offset  
 
 
 

As you can see above, with an offset, the drop shadow is no longer getting cut off at the corners; it is able to round off gracefully.

By default, the ApplyDropShadowEffect() function assumes that the light source is coming from the top-left (which is a good assumption); however, there is no way to set this. For fun, I tried to see if a negative offset would help give the illusion of a bottom light source, but it did not. The ApplyDropShadowEffect() function seems to take the absolute value of what ever offset is passed in.

The next effect that I wanted to try was the rounded corners. The only required parameter for this function is the target image object:

  • <!---
  • Let's round the corners of our image. By default
  • the CFImageEffects uses a white background with what
  • appears to be a 20 roundedness.
  • --->
  • <cfset objNewImage = objEffects.ApplyRoundedCornersEffect(
  • objImage
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get this new image:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Default Rounded Corners  
 
 
 

As you can see, when we pass in just the image, we get white rounded corners with a default roundness of about 20. In addition to the image, the ApplyRoundedCornersEffect() method also takes the color of the corners and the diameter of the roundness. Using these settings with black corners, we can get a better idea of what is going on:

  • <!---
  • This time, let's round the corners with a black
  • background so that we can really see what is going
  • on in the canvas.
  • --->
  • <cfset objNewImage = objEffects.ApplyRoundedCornersEffect(
  • <!--- Image. --->
  • objImage,
  •  
  • <!--- Background color of canvas. --->
  • "000000",
  •  
  • <!--- Roundedness. --->
  • 50
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get this new image:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Dark Rounded Corners  
 
 
 

With the black corners, we can see that things are tiny bit off. The original image seems to be shifted over and down one pixel, leaving us with a hairline black border along the top and left edges of the resultant canvas. I am sure this is just a minor bug that can easily be fixed.

The final effect that I wanted to take a look at was the reflection effect. This will make the image appear to be sitting on a reflective or glossy surface. This kind of effect has been popularized in applications like iTunes and many "Web 2.0" site designs. The only required parameter for this function is the target image:

  • <!---
  • Let's add a reflection to the image. This will make
  • the image appear as if it were resting on a glossy
  • or shiney surface.
  • --->
  • <cfset objNewImage = objEffects.ApplyReflectionEffect(
  • objImage
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get this new image:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Default Reflection Effect  
 
 
 

This gives a nice reflection effect with a height of about 40... but uh-oh, what happened? It looks like the rounded corner effect that we were examining earlier got somehow incorporated into this reflection affect. Looks like this is a little bug. If you look at the documentation for the rounded corner effect, you will read that it clearly states that it is returning a new image object:

Takes an image and returns a new image with rounded corners.

In fact, all of these methods, with the exception of DrawGradientFilledRect(), are supposed to return a completely new image. However, since none of our examples ever updated the original objImage variable, this leads me to believe that the ApplyRoundedCornersEffect() method is somehow updating the original image variable instead of updating a new image object.

No worries, minor bug. To counter that we can simply re-read in the image to which we want to apply the reflection effect. Since we are doing that, let's also use the optional parameters for background color of the expanded canvas, height of the reflection, and the starting opacity of the reflection:

  • <!---
  • Read in the test image to which we will be
  • applying the given effects.
  • --->
  • <cfimage
  • action="read"
  • source="./girl_with_fan.jpg"
  • name="objImage"
  • />
  •  
  • <!---
  • Let's add a reflection to the image. This will make
  • the image appear as if it were resting on a glossy
  • or shiney surface.
  • --->
  • <cfset objNewImage = objEffects.ApplyReflectionEffect(
  • <!--- Image. --->
  • objImage,
  •  
  • <!--- Background color of canvas. --->
  • "FFFFFF",
  •  
  • <!--- Height of reflection. --->
  • 75,
  •  
  • <!---
  • Starting opactiy. This is how transparent the
  • reflection is as the very bottom of the original
  • image.
  • --->
  • 30
  • ) />
  •  
  • <!--- Write new image to the browser. --->
  • <cfimage
  • action="writetobrowser"
  • source="#objNewImage#"
  • />

Running this code, we get this new image:


 
 
 

 
ColdFusion 8 CFImageEffects Component: Reflection Effect With Clean Image  
 
 
 

As you can see, now that we re-read the image prior to calling ApplyReflectionEffect(), we get a very nice, clean reflection effect.

While, I cannot give a full evaluation since I didn't actually try all of the effects, from what I did see, Foundeo's new CFImageEffects ColdFusion component is quite nice. There are few minor kinks to work out, but I am sure those things are very minor fixes. I like that the set of effects that this ColdFusion component provides is small. With the new Image manipulation functionality in place, I have a huge fear that people are going to start using it for things that really should be done by Image Manipulation Applications like Adobe Fireworks. I don't think Adobe every intended for the image manipulation feature set to be used in that capacity; rather, ColdFusion's new Image manipulaiton functionality should be used to help automate server-side image manipulation when using an Image Application is not a more appropriate choice.

Good job Foundeo! Looking forward to seeing where you take this.




Reader Comments

the other little minor bug is when you combine the rounded corner effect with the drop-shadow (the lower-right corner overlays the drop shadow). I found that while I wrote a quick little form that allows you to play with all the attributes of all the functions (except reflection) I wanted to see if I could use it to dynamically create a rounded-corner gradient rectangle with a drop shadow and Text over the top. Everything worked great other than those minor bugs

Reply to this Comment

@Michael,

That sounds like a cool little form you are building. I think CFImageEffects is pretty cool, so hopefully they can just iron out these minor issues like the one you found.

Reply to this Comment

Ben & Michael - thanks for your comments!

I think the documentation needs to be clear about which methods modify the image object you pass in and which return brand new image objects. All the methods return an image object, but some return a reference to the same object you passed in with a modified image. For performance reasons if I didn't need to create a new image object I didn't, so that's why it can be a bit confusing.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.