Analysis: ASCII art in colour

Although our pictures look nice enough, the real deal is working in colour: the end results offered are much more attractive, and finally make ASCII art look worthwhile.

Surprisingly, doing colour is easier than greyscale for the large part. This is because with greyscale we needed the array of symbols to be used for relative lightness of characters. Not so in colour. However, in colour we do need one thing that warrants me explaining it after pure ASCII art: you need to use the sprintf() function to convert RGB values into hex.

Because we'll be using the same ASCII character for every output pixel in our ASCII art image (we'll be using #), we need to use colour to distinguish the lightness of each pixel. So, when printing out each #, we need to also print out the relevant HTML code to make it coloured. In ou r previous code, the return value of imagecoloursforindex() was used to grab an array of red, green, and blue values between 0 and 255 for each pixel in the image. However, HTML takes its colour values as hexadecimal between 00 (decimal 0) and FF (decimal 255). As a result, we need to use sprintf() to convert our numbers into hexadecimal.

Parameter one to sprintf() is the format you'd like to output, and the subsequent parameters are values you'd like inserted into that format. For example, %s in a format string means "convert the relevant parameter to a string" before sending it to output. %X in a format string means "convert the relevant parameter to a hexadecimal number" before sending it to output. There are also modifiers for this parameter that allow us to control the length of the converted value, for example %2X means "convert this parameter to a hexadecimal value that must contain two digits". So if we supply the number 11, %2X will first convert it to hexadecimal, giving B, then, noting that it's less than two digits wide, will prepend a 0, giving 0B, which is just what we want for our HTML.

Here's the final code. Note that it also demonstrates loading a picture from a PNG file that also happens to be remote, and uses a different font size to blow the picture up:

  $image = imagecreatefrompng("");
  if ($image) {
    echo '<pre style="font: 4px/2px Courier New;">';
    $width = imagesx($image);
    $height = imagesy($image);
    for($y = 0; $y < $height; ++$y) {
      for($x = 0; $x < $width; ++$x) {
        $thiscol = imagecolorat($image, $x, $y);
        $rgb = imagecolorsforindex($image, $thiscol);
        $htmlcol = sprintf("#%2X%2X%2X", $rgb['red'], $rgb['green'], $rgb['blue']);
        $char = "<font color=\"$htmlcol\">#</font>";
        echo $char;
      echo "\n";
    echo '</pre>';

Because we've used # for every character in there, all the pixels have the same, squarish shape. You're welcome to try merging that code with the black-and-white code of multiple symbols, but you'll soon see the problem - using symbol complexity to mimic lightness mixed with using actual colour lightness means the lightness is exaggerated, making the detail hard to see.


Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Further Reading >>

Previous chapter: Development

Jump to:


Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.