Create an image with PHP pixel by pixel

It’s pretty easy to create an image with PHP pixel by pixel. I wanted a simple good looking graphic to show how close I am to completing my swimming goal, but I didn’t want to edit and upload a new picture every day.  I decided I wanted a simple text file to edit. I made a text file with a 20×20 grid of ‘o’s and replace an o with an x for every quarter mile I swim. So really what we end up doing is making a PNG file with PHP from an ASCII file.

Here’s the grid at the moment

xxxxxxxooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo
oooooooooooooooooooo

Pretty simple, right? Now I just needed a way to use that to make a pretty bitmap. Fortunately PHP has got all the tools for this.

First we create an image object:

$img = imagecreatetruecolor($width,$height); 

Now we need to read in the text file (‘swim’) and iterate over each character to see what it is:

$log = file_get_contents('swim');
$rows = explode("\n",$log);
foreach($rows as $y => $row){
    $columns = str_split($row);
    foreach($columns as $x => $column){
        // process each letter here!
    }

Inside the inner loop we’ll use a switch statement to decide what to do based on what letter we find.

// Inner loop code
    switch($column){
        case 'x':
            $color =  imagecolorallocate($img,0,0,0);
            break;
        case 'o':
            $color = imagecolorallocate($img,0,255,255);
            break;
        default:
            $color = imagecolorallocate($img,125,125,125);
        }
        imagesetpixel($img,$x,$y,$color);

Finally we print out the image

header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);

Now, the above code creates a usable image, but it’s only 20×20 pixels and the colors are kind of boring so I added the following two enhancements :

1) Enlarge the bitmap

I set the initial height and width with a variable instead of hard coding them, then re-use them here. $new_img will be $scale times larger than the original. Obviously, we will use $new_img in the imagepng() function to print it out instead of the smaller image.

$new_img = imagecreate($scale * $width,$scale * $height);
imagecopyresized($new_img,$img,0,0,0,0,$scale * $width,$scale * $height,$width,$height);

2) Add some color variation
I used the Gimp to find the RGB color ranges I wanted to use. I then put the minimum and maximum values into the rand function and every pixel will get a random different color within the range.

$color = imagecolorallocate($img,0,rand(216,255),rand(150,255));

My final script looks like this:

<?php

$width = 20;
$height = 20;
$scale = 10;
$img = imagecreatetruecolor($width,$height);

$black = imagecolorallocate($img,255,255,255);

$log = file_get_contents('swim');
$rows = explode("\n",$log);
foreach($rows as $y => $row){
    $columns = str_split($row);
    foreach($columns as $x => $column){
        switch($column){
        case 'x':
            $color =  imagecolorallocate($img,30,rand(0,100),rand(60,150));
            break;
        case 'o':
            $color = imagecolorallocate($img,0,rand(216,255),rand(150,255));
            break;
        default:
            $color = $black;
        }
        imagesetpixel($img,$x,$y,$color);
    }
}

$new_img = imagecreate($scale * $width,$scale * $height);
imagecopyresized($new_img,$img,0,0,0,0,$scale * $width,$scale * $height,$width,$height);

header('Content-Type: image/png');
imagepng($new_img);
imagedestroy($new_img);
imagedestroy($img);

The final image looks like this:

You can refresh this page to see that the image changes each time.

This entry was posted in Computers, Something Interesting and tagged , , , , . Bookmark the permalink.

One Response to Create an image with PHP pixel by pixel

  1. Brandon says:

    Wow, that is pretty cool and very creative. Nice job

Leave a Reply

Your email address will not be published. Required fields are marked *