ColdFusion 8 has introduced the CFImage tag and dozens of image manipulation functions. We have already looked at reading and writing image files and we have covered the basic yet powerful image manipulation that is possible through the CFImage tag actions alone. Now we know enough to be able to really start exploring the vast feature-set of ColdFusion 8 image manipulation. When it comes to something like this, your imagination is really the only limit, so it makes it a little bit more difficult to come up with simple ways to learn this stuff. I find that task-based learning works well and will allow us to accomplish real world goals while touching on many aspects of image manipulation.
For this post, we will cover adding watermarks to photos. There are a number of ways to do this including building the watermark from scratch and using an existing watermark image. To start with, I am going to demonstrate using an existing watermark image. Hands down, this is going to give you the best results. ColdFusion 8 provides amazing image manipulation, but it is certainly not a replacement for an image / photo editing application (and that was certainly never their intention) such as Adobe Fireworks.
To create my watermark image, I am going to open up my sweet-ass Fireworks application and create a transparent canvas. The transparent canvas is important because we don't want the overlaid image to be too obvious. Then, I am going to type out "Kinky Solutions" and give it an nice, orange glow affect:
| | | | ||
| | | |||
| | | |
Notice that the background of this canvas (in Adobe Fireworks) has that checkered white and gray pattern. This signifies that the background is transparent. Then, I export this image as a PNG32. This will compress the image while maintaining the transparency.
Now, let's take a look at the image that we are working with and the watermark that we are going to apply:
Launch code in new window » Download code as text file »
Running the above code, we get the following output:
| | | | ||
| | ![]() | | ||
| | | |
| | | | ||
| | | |||
| | | |
The watermark at this time is on a white background so you can't tell that it is transparent, but as you will see soon, the PNG image format keeps the same transparency that we had in our Fireworks application. Ok, so now what we're gonna do is read in both images and then paste the watermark onto the image of the girl with blue eyes (NOTE: I am adding a watermark for demonstration purposes, this photo is not my property nor the property of Kinky Solutions).
Launch code in new window » Download code as text file »
The above code uses some cool functions. After we read in the images, the first thing we do is turn on anti aliasing for future draw actions to the primary image. Anti aliasing gives things a slightly fuzzy look that can be more pleasing to the eye and help manipulations to appear more natural. The ColdFusion 8 documentation recommends turning this on for Paste actions. I would say that is especially true in this case where our watermark has a fuzzy edge due to the Glow affect we applied.
Whether you are setting the drawing anti aliasing, the background color, the drawing color, or the line stroke properties, understand that you are setting these properties for a specific image, not all images. Also understand that these properties will hold true for all image manipulation actions made to that specific image going forward or until the properties are explicitly changed.
Before we paste the watermark onto the original image, we set the drawing transparency to be 50 percent. This does not make the current image transparent; this makes all future draw actions 50% transparent when they are applied to the current image. The idea here is that not only are we using a watermark with a transparent background, when we paste it into the current image, we are going to adjust its alpha channel so that some of the original image shows up through the watermark.
The paste action itself is rather simple. It takes the source image, the target image, and the X and Y coordinates of where to paste the target image. The target image (second argument) is always pasted onto the source image (first argument). The X and Y coordinates are just like a web page - they start at the top left (0,0) and increase going down and to the right.
When I paste in the watermark, I am using the both the dimensions of the source and target images to calculate the X and Y coordinates of the paste. Notice that I am use the .GetWidth() and .GetHeight() actions. These are the undocumented, underlying Java methods available to the ColdFusion image object. If you are not comfortable, you can replace these with the more verbose ImageGetWidth() and ImageGetHeight() ColdFusion 8 methods.
Running the above code, we get a really nice Kinky Solutions watermark affect:
| | | | ||
| | ![]() | | ||
| | | |
Pretty slick. There is some graininess around the watermark, but in all fairness the glow effect plus the transparency plus the JPG optimization is just a bad combination for small file sizes. If I had exported this image as a PNG rather than a JPG, the quality would have been higher. So much of image manipulation magic is finding the right balance between quality and image size. You want things to look sweet, but you also don't want a 100K image that has no compression.
So what happens if you don't have an application like Adobe Fireworks to make your watermark image? Not all is lost. You can still create a watermark image manually and then paste it in using a similar technique. For this next demo, we are going to create a second image using ColdFusion 8 that has a gray box with the text, "Kinky Solutions," centered on it. Then, just as we did in the previous example, we are going to paste it over the original image:
Launch code in new window » Download code as text file »
Now, instead of reading in a watermark image, we are creating an entirely new image canvas using ImageNew(). ImageNew() takes the target image (left blank since we are creating it from scratch), the width and height, the image type, and the canvas color. For this image, we are using an RGB color set. This method can also take an ARGB color set, but the documentation is not very clear on what that is. I assume that the "A" stands for "Alpha", but I could not figure out how to make a transparent canvas (we will discuss doing this later on).
Once we have our canvas ready, we set our drawing color and then draw our rectangle, which is really just a border. I am using the ImageDrawRect() method rather than the ImageAddBorder() method as adding a border actually changes the size of the canvas; drawing a rectangle, on the other hand, gives us complete freedom to create a border of any dimension we want within the current canvas size. I am leaving out the sixth ImageDrawRect() argument which is a flag for filling the rectangle (with the same color as the border itself - the drawing color); we want the light gray of the canvas color to show through.
Next, we draw the Kinky Solutions text to the watermark. Before this action, we turn on the anti aliasing to give the text a more pleasing rendering. When we draw the text onto the canvas, we give it the X and Y coordinate and the text properties. The properties affect the font and size, but do not affect the text color. Text color is determined by the general drawing color set for the canvas (ie, SetDrawingColor()). Also, it is important to understand how text is drawn. I am not sure why this is exactly, but when drawing the text, the X and Y coordinates are for the bottom, left point of the text NOT the top, left. We are drawing our text at (14, 11), which you can clearly see is the bottom, left coordinate:
| | | | ||
| | ![]() | | ||
| | | |
And again, when we paste this watermark onto the source canvas, we want to paste with a 50% transparency. Notice this time, though, that we did not turn on anti aliasing for the source canvas. Our watermark has solid edges and a border. We don't really need this edge to be anti aliased.
Running the code above, we get:
| | | | ||
| | ![]() | | ||
| | | |
Clearly, this is not as nice as the first demo (at least in my opinion), but it does give you the ability to create a decent watermark if you don't have Fireworks. Also, we could technically have just drawn the watermark rectangle and the text directly onto the source image (the girl with the blue eyes) without having to create a watermark canvas; but, by creating a second canvas, I am able to demonstrate more ColdFusion 8 functionality.
In our first demo, we dealt with a PNG watermark that had a transparent canvas. In our second demo, we dealt with a watermark that had a rectangular, opaque canvas. What happens if we want to create a transparent canvas from scratch? There may be a way to create a transparent canvas inherent to ColdFusion 8, but I could not find it in the documentation or figure it out on my own. Transparent canvases, however, are really useful for things like watermarking, so being able to create them is important. In this next demo, I will show you how to create a transparent canvas using a neat little hack.
This transparent canvas hack relies on the fact that ColdFusion 8 can read in image data stored in a Base64 encoding. What we do it read in a new image using Base64 data that represents a 1x1 transparent GIF image. This will create an image that is 1x1 with a transparent canvas. Then, we just need to resize the image to be the dimensions of our desired canvas.
In this next demo, we will create a transparent watermark canvas from scratch using the above hack. Then will we will draw the text, "Kinky Solutions," blur the canvas, and then paste it over the source image:
Launch code in new window » Download code as text file »
Notice that the image we are reading in is the Base64 data:
R0lGODlhAQABAIAAAP///////yH5BAEHAAEALAAAAAABAAEAAAICTAEAOw==
This is the encoded 1x1 transparent GIF. We are also including the headers in the Base64 data, but this is not required (it works if you take it out); I left it in purely for demonstration purposes. Because we are using Base64 data, rather than an actual GIF image, it allows us to create transparent canvases without having a physical image on hand.
Running the above code, we get:
| | | | ||
| | ![]() | | ||
| | | |
Clearly, this is a hack. I am sure that ColdFusion 8 has a way to do this which is more elegant, but for now, until I can figure it out, this is a rather simple work-around. I hope, however, that you are beginning to see how amazing the ColdFusion 8 image manipulation functionality is.
Download Code Snippet ZIP File
Comments (1) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
Very nice work, I particulary like the first watermark. :)
And the transparent hack was a good idea also.
Good work
Posted by Shuns on Jun 18, 2007 at 9:27 PM