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.

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, even 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.

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 72×71 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.

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.

Draw Something Solver – The Platform

I have been putting some more thought into how to build my Draw Something Solver.

I have decided as I use Draw Something on my iPhone 4S, the solver should really run on there. This means coding using Objective C, or using HTML 5 and JavaScript.

As I haven’t written an HTML and JavaScript application for a while, and as it’s more fun, I think this should be the technology to use.

The only difficulty I can see is in getting screenshots from Draw Something into the application. Phonegap looks like it exposes some functionality to achieve this in JavaScript, so it looks like a good idea to use this as well. It also gives me the bonus of being able to create a native iOS application I could choose to upload to the App Store if I wanted, and also look a producing a version for Android in the future.

To give the application a native look and feel, using something like jQTouch or jQuery Mobile would make sense. jQuery Mobile has quite a lot of buzz at the moment and I’ve not had the opportunity to use it before, so I think I’ll try it out in this project.

Draw Something Solver – The Idea

I’ve been ill recently, and during my stay in hospital I discovered Draw Something. It’s basically a digital version of Pictionary played over the Internet on your phone.

I have noticed a few solvers have been written, and while I am recovering from my illness I have decided to try to write something to do the same function as I feel up to it, and to keep my skills up to date before I return to work.

I have an iPhone 4S, so anything I write about will be related to that device.

It seems the main tasks would be…

  • Obtain a list of words Draw Something uses
  • Obtain screenshots of the app
  • Extract words from the screenshots
  • Extract the number of letters in the solution from the screenshot
  • Find the possible words that match

Obtaining a list of words may be tricky as Draw Something uses quite a few proper nouns such as names. To start with the words on my Macbook in the /usr/share/dict/words file should be a good start until I find a better list.

The easiest way to get some screenshots would be to take them directly on my iPhone (press and hold the Home button then pressing the Sleep/Wake button, then using Preview on my Mac to import to my Macbook).

Extracting the number of words and number of letters in the solution from the screenshots will mean inspecting the image and doing some basic OCR.

Finding the possible words would be a case of sorting all the words into alphabetical lists of letters and comparing them.

To be continued…

JSON Config Files In Zend Framework

During a recent code review it was suggested that we should move from using an ini file to a JSON file for our Zend Framework application config file. The reason was to reduce duplication of data that can occur and instead move to a nicely nested file.

I wasn’t aware that JSON format config files were supported, but sure enough after a quick look at the Zend Framework documentation, there was the relevant class, Zend_Config_Json. It has only appeared in recent versions of the Zend Framework so that could be why I had missed it.

It’s easy to use in code, being almost a complete drop in for a the usual ini config.

$config = new Zend_Config_Json(
  './example_config.json',
  'production'
);

The first parameter is the location of the config file, the second is the section of the config file to use.

There is an optional third paramter that allows some addition configuration options to be specified such as changing the immutability of the config object once loaded, changing the behaviour of _extends, and the ability to ignore constants. More details can be found in options section of the Zend_Config_Json manual.

Here’s a quick example. Firstly the JSON configuration file.

{
  "production" : {
    "username" : "Robert Price",
    "beer" : [
      "Harveys Sussex Best",
      "Spitfire",
      "Asahi"
    ]
  },
  "testing" : {
    "_extends" : "production",
    "beer" : [
      "Harveys Star Of Eastbourne",
      "Schwaben Brau - Das Helle",
      "Brauhaus J.Albrect - Dunkel"
    ]
  }
}

OK, it’s a good real life example, but it has two sections, production and testing. Testing inherits from production by using the _extends parameter.
We can load and extract details using the following code.

$config = new Zend_Config_Json(
  './example_config.json',
  'production'
);
echo "Username is " . $config->username . "n";
echo "Favourite beers are...n";
foreach ($config->beer as $beer) {
  echo "* " . $beer . "n";
}

When you run this code you get the following results, assuming you saved the json config file from earlier as example_config.json

Username is Robert Price
Favourite beers are...
* Harveys Sussex Best
* Spitfire
* Asahi

Now change the code so instead of production when we load the config file, we use testing. Run the code and you’ll get the following…

Username is Robert Price
Favourite beers are...
* Harveys Star Of Eastbourne
* Schwaben Brau - Das Helle
* Brauhaus J.Albrect - Dunkel

As you can see my username has been inherited from the production block, but the list of beers has changed. This is a very powerful feature that lets you change a small section of data between environments in real code without having to repeat yourself and reduces the risk introducing errors in duplicated config options.

Adding Colour To A Mandelbrot Set

I was looking for a way to introduce some colour into my example Drawing A Mandelbrot Set With Zend PDF.

The method I settled upon was to use HSV – Hue, Saturation, Value.

I’m not an expert on colour theory, so I may not be the best person to describe how it works. The best way I can though, is to describe it as a cylinder, round the circumference is the hue, the radius is the saturation, and the height is the value. For a detailed definition, read the Wikipedia entry on HSL and HSV.

I can pick a hue and value, then just vary the saturation to give a nice graduated colour version of the earlier grayscale example.

Blue Mandelbrot

Alternatively I can pick a value and saturation, and vary the hue to give a vivid rainbow style fractal.

Vivid Mandelbrot

To achieve the first, we replace the code in the loop that prepared the grayscale colours, and instead generate our $colours array with the following…

list($red, $green, $blue) = hsvToRgb(0.5, $grayLevel, 1);
$colours[$i] = new Zend_Pdf_Color_Rgb($red, $green, $blue);

Firstly we get the values for $red, $green and $blue for a hue of 0.5 (blue), our varying $graylevel between 0 and 1, and a $value of 1 for the most vivid colours. After this we create a Zend_Pdf_Color and store it in the $colours array to use later.

To achieve the latter we just change how we call the hsvToRgb function.

list($red, $green, $blue) = hsvToRgb($grayLevel, 1, 1);
$colours[$i] = new Zend_Pdf_Color_Rgb($red, $green, $blue);

Now, you may have noticed that there isn’t a function called hsvToRgb available to PHP. Just drop in the following code.

function hsvToRgb ($hue, $saturation, $value)
{
  $rgb = array($value, $value, $value);
  if ($saturation != 0) {
    $varH = $hue * 6;
    $varI = floor($varH);
    $var1 = $value * ( 1 - $saturation );
    $var2 = $value * ( 1 - $saturation * ( $varH - $varI ) );
    $var3 = $value * ( 1 - $saturation * (1 - ( $varH - $varI ) ) );
    if ($varI == 0) {
      $rgb = array($value, $var3, $var1);
    } else if ($varI == 1) {
      $rgb = array($var2, $value, $var1);
    } else if ($varI == 2) {
      $rgb = array($var1, $value, $var3);
    } else if ($varI == 3) {
      $rgb = array($var1, $var2, $value);
    } else if ($varI == 4) {
      $rgb = array($var3, $var1, $value);
    } else {
      $rgb = array($value, $var1, $var2);
    }
  }
  return $rgb;
}

Drawing A Mandelbrot Set With Zend PDF

As you may know from some of my previous posts, I’ve been looking at Zend Framework’s PDF support.

As a bit of fun on the train home from work, I wondered if it would be possible to draw out a Mandelbrot Set using the PDF drawing functions in Zend_Pdf.

For those who don’t know what the Mandelbrot Set is, it is a fractal shape, and one of those projects every developer plays with at some point. It looks like my time has come here.

There is a reasonably simple formula for generating the image, we just need to iterate between a maximum and minimum x and y co-ordinate set and draw a pixel at each point when the number of iterations of the formula has reached a pre-defined number. In my example, I’m using 20 iterations, though you can go higher for greater accuracy. I won’t go over the formula, as it is explained in far greater depth than I have time for elsewhere on the internet.

In this code example, I’m using variables similar to those used in Mandelbrots formula, so they do trigger warnings with Zend Framework’s coding standards, but I think they make sense.

// load the Zend Framework Autoloader.
ini_set('include_path', './library');
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$maxIterations = 20;
$minX = -2;
$maxX = 1;
$minY = -1;
$maxY = 1;
try {
  // create a new PDF document.
  $pdf = new Zend_Pdf();
  // create a new A4 sized page.
  $page = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
  // calculate the width and height of the image to generate.
  $width = $page->getWidth();
  $height = $page->getHeight();
  if ($width > $height) {
    $width = $height;
  } else {
    $height = $width;
  }
  // prepare a black colour we can reuse when we draw the mandelbrot set.
  $black = new Zend_Pdf_Color_Html('#000000');
  // iterate over the mandelbrot set and draw it out.
  for ($x=0; $x<=$width; $x++) {
    for ($y=0; $y<=$height; $y++) {
      $c1 = $minX + ($maxX - $minX) / $width * $x;
      $c2 = $minY + ($maxY - $minY) / $height * $y;
      $z1 = 0;
      $z2 = 0;
      for ($i=0; $i<$maxIterations; $i++) {
        $newZ1 = $z1 * $z1 - $z2 * $z2 + $c1;
        $newZ2 = 2 * $z1 * $z2 + $c2;
        $z1 = $newZ1;
        $z2 = $newZ2;
        if ($z1 * $z1 + $z2 * $z2 >= 4) {
          break;
        }
      }
      // if we reach max iterations, draw a black pixel
      if ($i >= $maxIterations) {
        $page->setFillColor($black)
             ->setLineColor($black)
             ->drawRectangle(
               $x,
               $y,
               $x+1,
               $y+1,
               Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE
             );
      }
    }
  }
  // add the page to the pdf document.
  $pdf->pages[] = $page;
  // save the finished PDF to a file
  $pdf->save('fractal.pdf');
  // catch any errors
} catch (Zend_Pdf_Exception $e) {
  die('PDF error: ' . $e->getMessage());
} catch (Exception $e) {
  die ('Error: ' . $e->getMessage());
}

You will need to run this code on the command line, and it will take a few seconds to execute. When complete, you will have a PDF document with the following image.

Mandelbrot set rendered from a PDF

We can refine this slightly to get a prettier picture if we show the number of iterations used in a different colour, instead of just showing black if we go over our limit of maximum iterations.

To do this, we’d need to prepare an associative array with a colour for each iteration. The easiest option is to use grayscale and Zend_Pdf_Color_GrayScale. After we work out the max width and height, insert the following code.

// prepare colours
for ($i=0; $i >= $maxIterations; $i++) {
  $grayLevel = $i / $maxIterations;
  $colours[$i] = new Zend_Pdf_Color_GrayScale($grayLevel);
}

Now we have an associative array to look up a different shade of gray from 0 to $maxIterations.

Instead of the code that checks if $maxIterations has been reached and then draw a black pixel, we can replace it with the following

$page->setLineColor($colours[$i])
     ->setFillColor($colours[$i])
     ->drawRectangle($x, $y, $x+1, $y+1, Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE);

Run this modified script on the command line, and you’ll generate a PDF with the following image.

Mandelbrot set rendered from a PDF in grayscale

That image looks great, but not very colourful. I’ll cover how to get some colour in there another time.

Drawing A Image In A PDF With Zend Framework

I recently wrote about Creating A Simple PDF With The Zend Framework, and so I thought I’d take a quick look at Zend_PDF’s Drawing Methods.

As you may know I work for a company called Bauer and we have a very simple logo. It’s basically a blue square, with a gray triangle in the top right hand corner and the name BAUER in white at the bottom. This sounds like an ideal image to try to recreate using Zend_PDF.

Bauer Media Logo

Take a look at my previous article on PDF’s and Zend Framework for an explanation of setting up a document and page to draw on. I will assume this page has been setup and is available in the $page variable.

Firstly we need to prepare a font for use. I don’t know the font Bauer use, so I’ll just use Helvetica Bold in this example.

$font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD);

The background is a blue square, so I need to set the fill colour to the shade of blue Bauer use, then draw the square using this colour.

$page->setFillColor(new Zend_Pdf_Color_Html('#014495'))
     ->drawRectangle(0, 0, 200, 200, Zend_Pdf_Page::SHAPE_DRAW_FILL);

As you can see, I’ve decided to make the logo 200×200 in size.

Now it’s time to write BAUER at the bottom in white using the font we prepared earlier.

$page->setFillColor(new Zend_Pdf_Color_Html('#ffffff'))
     ->setFont($font, 52)
     ->drawText('BAUER', 7, 10);

Firstly I set the fill colour to white. Next I select the font and set it’s size. Finally I write the word BAUER at co-ordinates 7,10, which happens to be at the bottom of the blue square.

Finally it’s time to draw the gray triangle in the top right corner of the blue square.

$page->setFillColor(new Zend_Pdf_Color_Html('#dddddd'))
     ->drawPolygon(array(70, 190, 190),
                   array(190, 190, 70),
                   Zend_Pdf_Page::SHAPE_DRAW_FILL);

As before, I set the fill colour, this time to gray. Now I use the drawPolygon method to draw the triangle. As you can see there are two arrays there, the first are the x co-ordinates of the triangle, the second are the y co-ordinates of the triangle. The fill method is the last parameter, it’s the same as the one we used when drawing the blue square.

We should now have our Bauer logo on the page!

generated copy of the Bauer Media logo

I don’t think that Bauer will be sacking their design team in a hurry, but it’s quite a close approximation of the logo.

Here’s a copy of the finished code.

// load the Zend Framework Autoloader.
ini_set("include_path","./library");
require_once 'Zend/Loader/Autoloader.php';

$loader = Zend_Loader_Autoloader::getInstance();

try {
  // create a new PDF document.
  $pdf = new Zend_Pdf();

  // create a new A4 sized page.
  $page = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);

  // prepare the Helvetica Bold font.
  $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD);

  // draw the blue square background.
  $page->setFillColor(new Zend_Pdf_Color_Html('#014495'))
       ->drawRectangle(0, 0, 200, 200, Zend_Pdf_Page::SHAPE_DRAW_FILL);

  // draw the white BAUER text at the bottom of the square.
  $page->setFillColor(new Zend_Pdf_Color_Html('#ffffff'))
       ->setFont($font, 52)
       ->drawText('BAUER', 7, 10);

  // draw the grey triangle in the top right corner of the square.
  $page->setFillColor(new Zend_Pdf_Color_Html('#dddddd'))
       ->drawPolygon(array(70, 190, 190),
                     array(190, 190, 70),
                     Zend_Pdf_Page::SHAPE_DRAW_FILL);

  // add the page to the pdf document.
  $pdf->pages[] = $page;

  // save the finished PDF to a file
  $pdf->save('bauer.pdf');

// catch any errors
} catch (Zend_Pdf_Exception $e) {
  die('PDF error: ' . $e->getMessage());
} catch (Exception $e) {
  die ('Error: ' . $e->getMessage());
}