Lets build an HTML5 app

HTML5 rocks! Today we are going to build a simple JavaScript/HTML5 application that uses the canvas api to convert colour images to black and white. This application includes a php hack that solves the canvas api same origin policy which prevents manipulation of images from a different domain.

Backend: Our php hack - fetch_image.php

Fetches the image file and loads it as a local resource (Remember to sanitize all input).

if (isset($_GET['url']) && !empty($_GET['url']))
    $url = $_GET['url'];
    $file_format = pathinfo($url, PATHINFO_EXTENSION);
        header("Content-Type: image/$file_format");
        header("Content-disposition: filename=image.$file_format");
        $img = @file_get_contents($url);
       if ($img)
       echo $img;
    catch(Exception $e)
        echo $e->getMessage();
    die('Unknown request');

Front-end: index.html

This is our basic html front-end, we will not worry too much about the css because it is not the focus of this article, however the file will be included in the demo files.

<!DOCTYPE html>
<meta charset="utf-8">
<title>RGB to Grayscale</title>
<link rel="stylesheet" href="style.css" type="text/css" />
  <h1>RGB to Grayscale</h1>
  <form action="#" method="GET" id="webimage">
    <input name="url" id="url" type="text" placeholder="Enter image url" />
    <input value="Grayscale"  id="submit" name="Submit" type="button">
  <div id="container">
    <div id="mainloader" class="loader waiting" >
    <div id="sideloader" class="loader waiting">
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
  <script type="text/javascript" src="app.js"></script>

Front-end: JavaScript - app.js

Firstly we need some functions to handle the basic tasks for the application.

//Function for outputting messages
function showMSG(msg) {
    var elem=$('<div>',{
    elem.click(function () {
        $(this).fadeOut(function () {
    setTimeout(function () {
    }, 5000);

//Function for testing if canvas is supported
function isCanvasSupported() {
    var elem = document.createElement('canvas');
    return !!(elem.getContext && elem.getContext('2d'));

//Grayscale algorithm
function toGreyScale(r, g, b) {
    return r * 0.2989 + g * 0.5870 + b * 0.1140;

The next function performs the core task of our application and it takes two parameters - an image object and a div ID. The image object is rendered on canvas and manipulated to black and white.

function editImage(img, targetDiv) {
    var id = "canvasID",
        canvasContainer = document.getElementById(targetDiv),
        imgCanvas, ctx, imageData, px, len, i, redPx, greenPx, bluePx, greyscale;
    //create canvas element and give it attributes
    imgCanvas = document.createElement("canvas");
    imgCanvas.id = id;
    imgCanvas.width = img.width;
    imgCanvas.height = img.height;

    //Append canvas to a div inside an html document

    //locate the canvas within the html document
    imgCanvas = document.getElementById(id);
    ctx = imgCanvas.getContext("2d");

    //Draw the image on the canvas from the top-left(0, 0) corner
    ctx.drawImage(img, 0, 0);

    //Access the image data and its pixels
    imageData = ctx.getImageData(0, 0, img.width, img.height);
    px = imageData.data;
    len = px.length; //count pixels

    //loop over the pixels and grab RGB values
    for (i = 0; i < len; i += 4) {
        redPx = px[i];
        greenPx = px[i + 1];
        bluePx = px[i + 2];
        //convert RGB to grayscale
        greyscale =  toGreyScale(redPx, greenPx, bluePx);
        //store the greyscale values
        px[i] = greyscale;
        px[i + 1] = greyscale;
        px[i + 2] = greyscale;

    //Clear the canvas
    ctx.clearRect(0, 0, img.width, img.height);
    //Draw the new image
    ctx.putImageData(imageData, 0, 0);

Lastly we use jQuery to handle interaction with the interface.

$(function () {
    var canvas_support = isCanvasSupported();
    if (!canvas_support) {
        showMSG("Your browser does not support HTML5 Canvas");

    $('#url').focus(function () {

    $('#submit').click(function () {
        var img = new Image(), url = $('#url').val(), loader = $('.loader');
        $("#mainloader, #sideloader").empty()
        $(img).load(function () {
            var $this = this, w = $this.width, h = $this.height;
            $("#sideloader").animate({"width": w, "height": h}, 500);
            .animate({"width": w, "height": h}, 500, function () {
                setTimeout(function () {
                    editImage(img, 'sideloader');
                }, 1000);
        .error(function () {
            $('#mainloader, #sideloader')
            showMSG("Errror in loading image");
        .attr('src', 'fetch_image.php?url=' + url);
comments powered by Disqus