Image Editing with JavaScript, AJAX, PHP and GD

Posted on March 9, 2009 Categories: Coding

post author

Written by: Charles

Charles has spent the past few years as the big cheese at thrudigital. On any normal day you will catch him with a milky cup of tea (no bubbles on top thank you very much) and at least 30 browser tabs open.

Ever wanted to allow your users the ability to create and edit images within their browser?

Options

There are a number of different ways you can achieve this sort of functionality:

  • Using a Flash or Flex application;
  • Using the <canvas> element from the HTML 5 Working Draft specification
  • Using AJAX, sending requests to the server which takes each edit request, manipulates the image and sends back the result

Canvas support across the browsers that our users have installed is still patchy at best: It is supported by recent versions of Safari, Opera and Firefox – but support from Internet Explorer is still lacking. Some talented individuals have started to find creative solutions to this current lack of support.

The AJAX Way

The example I am going to use is very simple – allowing a user to paint bucket tool to flood fill colour on an image. This example could easily be expanded to use any of the image manipulation functions that the PHP GD library provides.

User interface

The first thing we need is an HTML page which will serve as the interface to our paint bucket app:

<img id="picture" src="picture.png"/>
<form action="paintbucket.php">  <input id="x" name="x" type="text" value="" />
  <input id="y" name="y" type="text" value="" />
  <input id="red" name="red" type="text" value="255" />
  <input id="green" name="green" type="text" value="0" />
  <input id="blue" name="blue" type="text" value="0" />
  <input id="image" name="image" type="text" value="" />
</form>

Client-side script

Then we need a client-side script to detect when the user clicks on the image, populates our hidden form and sends the form data as an AJAX request. The jQuery library has been used, as has the getRelativeCoordinates function from this post by Acko:

$(document).ready(function() {

  // Reset all form values
  $('form input').val('');
  $('form input#red').val('255');
  $('form input#green, form input#blue').val('0');

  // Add click and paint behaviour to picture
  $('#picture').click(function(event) { sendPaintRequest(event); });
});

function sendPaintRequest(event) {

  // Get co-ordinates of mouse click and put into form fields
  coordinates = getRelativeCoordinates(event, $('#picture')[0]);
  $('#x').val(coordinates['x']);
  $('#y').val(coordinates['y']);

  // Post form data
  data = $('form').serialize();
  jQuery.post('paintbucket.php', data, function(data) { receivePaintResponse(data); }, 'json');
}

function receivePaintResponse(data) {

  // Get image data from response and update the picture
  $('#picture').attr('src', data.image);

  // Put image data into form field for next request
  $('#image').val(data.image);
}

Server-side script

Then we need a server-side script (PHP) to process the paint request and pass back the modified image to the client as a base64 encoded PNG.

<?php

  $x = intval($_POST['x']);
  $y = intval($_POST['y']);
  $red = intval($_POST['red']);
  $green = intval($_POST['green']);
  $blue = intval($_POST['blue']);

  // Set configuration
  $encodedPngHeader = 'data:image/png;base64,';
  $tempFileName = 'temp.png';

  if ($_POST['image'] != '') {

    // Decode image data
    $encodedImageData = $_POST['image'];
    $decodedImageData = base64_decode(str_replace($encodedPngHeader, '', $encodedImageData));

    // Write decoded image data to file
    file_put_contents($tempFileName, $decodedImageData);

    // Create image from file
    $image = imagecreatefrompng($tempFileName);

    // Delete file
    unlink($tempFileName);

  } else {

    // Get the original image from on the server
    $image = imagecreatefrompng('picture.png');
  }

  // Fill image with color at the specified co-ordinates
  $color = imagecolorallocate($image, $red, $green, $blue);
  imagefill($image, $x, $y, $color);

  // Write filled image to file
  imagepng($image, $tempFileName);

  // Read image data from file and encode it
  $imageData = file_get_contents($tempFileName);
  $encodedImageData = 'data:image/png;base64,' . base64_encode($imageData);

  // Delete file
  unlink($tempFileName);

  // Send JSON response with encoded image data
  $response = array('image' => $encodedImageData);
  header('Content-Type: application/json');
  print json_encode($response);

?>

That’s it!

This is a very simplified example, but you could see how this method could be expanded provide any sort of drawing functionality, and combined with the use of JavaScript controls in the user interface (e.g. a colour picker).

Follow us:

1 Response

  1. sandy
    May 28, 2010

Leave a Reply

Archive

July 2010

June 2010

May 2010

April 2010

March 2010

February 2010

January 2010

December 2009

November 2009

May 2009

April 2009

March 2009

February 2009

January 2009

December 2008

November 2008

October 2008

September 2008

July 2008

June 2008

March 2008

February 2008

January 2008

December 2007

November 2007

October 2007

About Us

A team of nerds, creatives and strategy ninjas based in central London, building websites, social networks, widgets and social media apps.

We have a portfolio that is good enough to make a male peacock blush, and some killer outside-the-box products...in a box.
Ask us a Question

Blog posts