Last week, I explored the HTML Canvas element for the first time. In that exploration, I created a "finger painting" demo for the iPhone that would post drawing commands to the server where the image would be re-created as a PNG in ColdFusion. That was a nice approach because it gave me some flexibility in how the ColdFusion image was created (using anti-aliasing and a thicker pen stroke). But, I wanted to see if there was a way to extract image data from the canvas without having to track every single drawing action performed by the user.
As it turns out, the HTML canvas element has a toDataURL( mimeType ) method. This method takes the current canvas display and returns a base64-encoded data URL of the pixel data for the given mime-type. This sounded like something that would play very nicely with ColdFusion's ImageReadBase64() method, which can create a new image object from a base64-encoded data URL.
Taking my iPhone drawing demo from last week, I refactored it to use the toDataURL() method. Now, rather than storing every single drawing command, I simply export the base64 image data and store it in a hidden form field before I post the form to the ColdFusion server.
As you can see, clicking on the "Export Graphic" button stores the base64 image data to the form field, "imageData". Because the base64 data contains all information about the image, including the height and width, I no longer need to post the canvas dimensions along with the form submission.
Once we post to the ColdFusion server, the code server-side has been greatly simplified; we are no longer re-creating the image step-by-step, we are simply creating an image object based on the submitted base64-encoded image data URL:
<!--- Param the base64 encoded image data value. ---> <cfparam name="form.imageData" type="string" default="" /> <!--- Create a new ColdFusion image with the given dimensions. ---> <cfset image = imageReadBase64( form.imageData ) /> <!--- Now that we have drawn the image, write it to the browser as a PNG file. ---> <!DOCTYPE HTML> <html> <head> <title>iPhone Touch Events With jQuery</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <h1> Your iPhone Touch Drawing </h1> <p> <cfimage action="writetobrowser" source="#image#" style="border: 1px solid ##999999 ;" /> </p> <p> <a href="./index.cfm">Draw Another Image</a> </p> </body> </html>
As you can see, the ColdFusion image is created with a single line of code - one call to imageReadBase64(). This is extremely simple; but, at the same time, as I mentioned above, we have much less flexibility as to how the image is rendered. In my previous experiment, the re-created ColdFusion image had "nicer" anti-aliasing and a thicker pen stroke. Of course, "nicer" is a highly subjective term.
Using this approach, the following drawing:
... gets exported and re-created as this:
As you can see, the re-created ColdFusion image is a bit jagged in its lines.
The Canvas element is a lot of fun to play with; of course, keep in mind that the Canvas element is not yet supported by all the major browsers (think: IE). As such, it can only really be used in research and development - probably not as a mission-critical solution.
Want to use code from this post? Check out the license.