Hello, and welcome to the online home of Robert Price - Software Architect for web and mobile at multinational media company Bauer (but don't let that put you off).

Here you'll find Rob's blog, focusing mainly on web and mobile technology, but anything can (and does) get posted here.

Latest Blog Entries

Using The DOM Ready Event

One of the great advantages of using a library like jQuery is that is provides functions like ready() so you can activate your JavaScript code when the DOM is ready, and not when everything has been loaded. This can be significantly earlier, especially if you an image heavy page.

The ready() function is quite chunky, and has to account for a variety of browsers and versions. However, if you know you are running on a recent browser, you can always look at hooking directly into the DOMContentLoaded event. This is part of the HTML5 spec.

To use it you need to add an event listener using the document.addEventListener method. This takes two parameters, the name of the event - in this case DOMContentLoaded, and a callback function to call when the event is triggered.

document.addEventListener("DOMContentLoaded", function domready() { document.removeEventListener("DOMContentLoaded", domready); console.log("DOM Ready"); });

Notice how I have given the function a name - domready(), this is so I can unhook the function from the event listener once the event has fired.

Entered: 2012-05-09 16:01:14

Grayscaling An HTML5 Canvas

I've been looking at how to turn a colour image into a grayscale one using JavaScript on an HTML 5 Canvas. I had done something similar a few years back to an image using Perl.

Wikipedia has a good article on converting colour to grayscale, and it's very simple formula based on the luminance of the image. The recommendation is to add together 30% of the red value, 59% of the green value and 11% of the blue value.

var luma = red * 0.3 + green * 0.59 + blue * 0.11;

We can easily apply this formula over the ImageData in an HTML 5 Canvas Context object to turn the image held in the Canvas to grayscale. The ImageData.data holds an array with four pieces of data per pixel, the red, the green, the blue and the alpha values. These are integer values between 0 and 255. The code to grayscale the ImageData would look like this.

for (var i = 0; i < imageData.data.length; i+=4) { var luma = Math.floor(imageData.data[i] * 0.3 + imageData.data[i+1] * 0.59 + imageData.data[i+2] * 0.11); imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = luma; imageData.data[i+3] = 255; }

Notice the use of Math.floor(), this is just to round the luminance down into an integer value.

Colour

Grayscale

There is another common way to grayscale an image, and that is to get the red, green and blue pixels to all match. You can pick the colour you want to be the key, for example red, then just make sure the values for the green and blue for each pixel match that of the red one. This is making use of a single channel, and can give very different effects depending on your source image.

To use the red channel we could the following code over some ImageData.

for (var i = 0; i < imageData.data.length; i+=4) { imageData.data[i+1] = imageData.data[i+2] = imageData.data[i]; imageData.data[i+3] = 255; }

Grayscale Red Channel

To use the green channel, use the following.

for (var i = 0; i < imageData.data.length; i+=4) { imageData.data[i] = imageData.data[i+2] = imageData.data[i+1]; imageData.data[i+3] = 255; }

Grayscale Green Channel

To use the blue channel, use the following.

for (var i = 0; i < imageData.data.length; i+=4) { imageData.data[i] = imageData.data[i+1] = imageData.data[i+2]; imageData.data[i+3] = 255; }

Grayscale Blue Channel

Entered: 2012-05-08 18:08:45

Scaling An Image In An HTML5 Canvas

As part of my Draw Something Solver, I've been working with HTML 5 Canvas objects quite a bit. As I want my application to work on all iPhones, I need to support both regular and retina displays. As I need to detect the letters on the image, I really need the images to be of the same size, however a regular image is 320x480, whereas a retina image is 640x960.

The eagle eyed amongst you will see that this is a factor of 2 difference between the two.

The Canvas Context object provides a scale() method, that you pass in x and y scaling factors into.

So if I have a Canvas object called screenshotCanvas, and an Image object called screenshotImage I want to scale down by half, I can use the following JavaScript code.

screenshotCanvasContext = screenshotCanvas.getContext('2d'); screenshotCanvasContext.scale(0.5,0.5); screenshotCanvasContext.drawImage(screenshotImage, 0, 0, screenshotImage.width, screenshotImage.height);

If I want to double the image in size, I just change the scale factor to 2.

screenshotCanvasContext = screenshotCanvas.getContext('2d'); screenshotCanvasContext.scale(2,2); screenshotCanvasContext.drawImage(screenshotImage, 0, 0, screenshotImage.width, screenshotImage.height);

Entered: 2012-05-07 22:04:07

Serialising A JavaScript Object To JSON

As part of my Draw Something Solver I needed to convert a JavaScript object to a string of JSON data. In the past I'd have resorted to a bit of library code, but as I am coding to a recent version of Safari, I thought I'd try to inbuilt JSON functions available to a modern browser.

The method I needed is JSON.stringify(), and it's very easy to use.

var text = JSON.stringify(myObject);

The above example serialises myObject into text.

There is an equivilant method, JSON.parse() that can be used to safely take a text JSON string and turn it into an object without relying on JavaScript's eval() function.

There is a useful chart showing JSON support in modern browsers over at caniuse.com.

Entered: 2012-05-05 23:24:04
Modified: 2012-05-05 23:32:38

Draw Something Solver - First OCR Attempt

As part of my Draw Something Solver, I have worked out how to load and extract images from an HTML 5 canvas, now I need to work out what letters the images represent.

I am hoping that as the images of the letters are all computer generated I can simply compare them and create a lookup table.

I initially tried a basic serialisation by running join() over the ImageData as it was type of array, but this didn't work as it wasn't an array as such.

Canvases offer a toDataURL() method, that saves the canvas out as a base64 encoded png or jpeg image. Base64 is a text based encoding, so could be suitable. When I tried this, I found the string to be very long, and not very pratical to use.

So I have a long unique string I need to perform a lookup and match against, this is crying out for a hashing function to turn it into something more manageable.

JavaScript doesn't have a native hashing function like some languages. I found a good JavaScript SHA1 script so used this to get the encoded images down to a more manageable 40 characters.

Running the resulting code over several images has produced some disappointing results. Not all letters appear to consistantly encode to the same SHA1 hash, which means there is some tiny difference in the images of the letters sometimes, evem though visually they look the same to the human eye.

I now need to look at another approach for letter detection. There are two I can think of, the first is to convert the image into one less complex, a simple black and white image that should hopefully be more likely to match. The second is to investigate full OCR technology.

I have looked at Grayscaling Image With Perl in the past, so I hope I can reuse that knowledge again with this project.

Entered: 2012-05-04 23:42:18

Extracting And Drawing Part Of An Image Into An HTML5 Canvas

As part of my Draw Something Solver, I need to be able to extract the letters from the screenshot image.

I've already looked at loading an image into a HTML 5 canvas object in an earlier post, so I will assume that code is already in place.

It's actually very easy to extract part of an image from a canvas, we just need to use the getImageData() method from the canvas context object. This takes 4 parameters, the x and y coordinates for the top left corner of the image, and width and height to extract.

var letterImageData = dsCanvasContext.getImageData(27, 782, 72, 71);

In this case, I'm cutting out a 72x71 block starting from the coordinates 27,782.

If you need to paste this extract into another canvas, or even the same canvas, you can use the putImageData method on the canvas context object. This takes 3 parameters, the ImageData you wish to draw into the canvas, and the top left x and y coordinates to draw it into.

dsCanvasContext.putImageData(letterImageData,0,0);

This will post into the top left hand corner of the original canvas.

Entered: 2012-05-04 22:58:31
Modified: 2012-05-07 22:04:21

Loading An Image Into An HTML5 Canvas

As part of my Draw Something Solver, I need to be able to load an image into an HTML 5 Canvas. I thought I'd share the solution to help others.

Firstly, assume you have an HTML page with an empty canvas element called drawsomething. Secondly, assume the image you want to load is next to the HTML page and is called testimage.png.

I'm not usng a framework like jQuery in this example, so the code may a bit verbose.

Firstly, you want the code to run when the page has finished loading, the easiest way to do this is to tie into the window.onload event. If yoou were using jQuery or similar, ready would be a good point to use.

window.onload = function() { // code goes here }

Now we need to get the canvas element and it's context. We can do this with the following code.

var dsCanvas = document.getElementById('drawsomething'); var dsCanvasContext = dsCanvas.getContext('2d');

We need an Image object to load the image into...

var screenshotImage = new Image();

When the image has been loaded, we need to draw it into the canvas. Do to this we can hook into the image objects onload event and place our canvas manipulation code into an anonymous function that is called when the event triggers.

Inside the anonymous function, we resize the canvas to the same size as the image and call the canvas context's drawImage() method, passing in the image, it's start x and y coordinates, and the width and height of the image.

screenshotImage.onload = function() { dsCanvas.width = screenshotImage.width; dsCanvas.height = screenshotImage.height; dsCanvasContext.drawImage(screenshotImage,0,0,screenshotImage.width, screenshotImage.height); }

Finally, we assign a filename to the image object's src attribute. This will cause the image object to load the image, and when loaded it will trigger the onload event we have just written to draw the image into the canvas.

screenshotImage.src = "testimage.png";

The complete example looks like this...

window.onload = function() { var dsCanvas = document.getElementById('drawsomething'); var dsCanvasContext = dsCanvas.getContext('2d'); var screenshotImage = new Image(); screenshotImage.onload = function() { dsCanvas.width = screenshotImage.width; dsCanvas.height = screenshotImage.height; dsCanvasContext.drawImage(screenshotImage,0,0,screenshotImage.width, screenshotImage.height); } screenshotImage.src = "testimage.png"; }

Next time, I will look at how to manipulate the image that has just been loaded into the canvas.

Entered: 2012-05-03 19:37:27
Modified: 2012-05-07 22:04:32

>> Continue reading blog entries...