Image reflection w/CFIMAGE
Posted At : October 10, 2007 2:02 PM
| Posted By : Dave
Related Categories:
ColdFusion 8
The new image cfimage has tons of functionality. There are even things you can do with it that are not clearly stated. For instance, adding a reflection to an image. This is something you can do in javascript. However, this requires client side processing as well as cross browser and layout issues to. But, if the reflection could be done on the server most if not all these issues go away.
There were a couple challenges to overcome when trying to figure this out. First, normally you would do a reflection by making reflection part fade by using the alpha layer. Using cfimage this is not possible. There is no way to control the alpha layer (that I have found). Also, there were performance issues to take into consideration since you are processing the image and displaying it instead of just displaying it.
The first challenge was overcome by simply drawing lines on the reflection part. The lines are varied levels of transparency so it simulates a fade. The performance issue became a non issue after working with the code. I was able to get the processing of a 400x400 200k jpg down to 120ms. Of that 120ms, 80ms was spent reading in the file.
The function is quite simple. All you have to do is pass it an image variable. From there a canvas is created that is the size of the source plus the size of the reflection. Next the bottom of the image is copied off and flipped as the reflection. We then draw on the flipped part to simulate a fade. At the end we put it all together and return the newly reflected image.
I added a couple fun things to it like being able to blur or negative the reflection.
Here it is in all its glory:
<CFIMAGE source="#thisImg#" action="writeToBrowser">
<CFFUNCTION NAME="doReflection" RETURNTYPE="ANY" OUTPUT="false" HINT="creates reflection and returns image object">
<CFARGUMENT NAME="image" TYPE="any" REQUIRED="true" HINT="Image Object" />
<CFARGUMENT NAME="Height" TYPE="numeric" REQUIRED="false" DEFAULT="0" HINT="reflection height, default is 1/3 source image height" />
<CFARGUMENT NAME="opacity" TYPE="numeric" REQUIRED="false" DEFAULT="85" HINT="reflection opacity percentage (0 - 100)" />
<CFARGUMENT NAME="bgColor" TYPE="string" REQUIRED="false" DEFAULT="white" HINT="background color behind image" />
<CFARGUMENT NAME="blur" TYPE="BOOLEAN" REQUIRED="false" DEFAULT="false" HINT="blur the reflection" />
<CFARGUMENT NAME="negative" TYPE="BOOLEAN" REQUIRED="false" DEFAULT="false" HINT="negative the reflection" />
<CFSCRIPT>
var localImg = arguments.image;
var theInfo = ImageInfo(localImg);
var imgWidth = theinfo.width;
var imgHeight = theinfo.height;
if (arguments.Height EQ 0){
arguments.Height = ceiling(imgHeight/3);
}
if (arguments.Height gt imgHeight){
arguments.Height = imgHeight;
}
variables.reflected = ImageNew("", imgWidth, imgHeight+arguments.Height, "argb", arguments.bgColor);
imageSetAntialiasing(variables.reflected,"on");
variables.reflectPart = ImageCopy(localImg, 0, imgHeight-arguments.Height, imgWidth, arguments.Height);
imageFlip(variables.reflectPart, "vertical");
variables.DrawEnd = 50/arguments.height;
imageSetAntialiasing(variables.reflectPart,"on");
ImageSetDrawingColor(variables.reflectPart, arguments.bgColor);
for (i = 0; i lte (arguments.height-1); i = i + 1) {
ImageSetDrawingTransparency(variables.reflectPart, round(DrawEnd*i*2));
ImageDrawLine(variables.reflectPart, 0, arguments.Height-i, imgWidth, arguments.Height-i);
}
ImagePaste(variables.reflected, arguments.Image, 0, 0);
ImageSetDrawingTransparency(variables.reflected, 100-opacity);
if (blur){
imageBlur(variables.reflectPart);
}
if (negative){
imageNegative(variables.reflectPart);
}
ImagePaste(variables.reflected, variables.reflectPart, 0, imgHeight);
return variables.reflected;
</CFSCRIPT>
</CFFUNCTION>
Have fun...
--Dave
