Creating a service which converts images to ASCII in PHP
Have you ever wanted to send, display or use colored ASCII versions of real images? Well, it turns out this is not something very hard to achieve with PHP. In this tutorial, we are going to create a simple class which has the capabilities to convert all kinds of URLs to jpg/gif/png images to ASCII and show the ASCII in dimensions specified by the user (we shall resize the image to the specified by the user dimensions before converting it to ASCII). Furthermore, we will build a simple web interface where users can give URLs to images and their desired dimensions and see the ASCII output as well as the HTML code that they can use to add the ASCII elsewhere.
Below are some screenshots of the service.
Creating the Image to ASCII and Image resize class
To start with, we hide potential errors from being displayed and initialize our class.
1 2 3 4 5 6 7 | <?php ini_set(“display_errors”, “off”); //accepts a path to an image, and the desired width/height of the ASCII class ImageToAscii { |
We want to initialize the class at least with a path to an image and optionally with x and y dimension of the ASCII. In our constructor method, we set the appropriate properties and we prepare for resizing the image. By default, ASCII with 90×40 dimensions is going to be shown to the user. The users can change that up to 600×600.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private $file = null; private $img = null; private $error = null; public function __construct($file, $resizeX,$resizeY) { $this->file = $file; $this->resizeX = $resizeX; $this->resizeY = $resizeY; if (!($this->resizeX && $this->resizeY && is_numeric($this->resizeX) && is_numeric($this->resizeY) && (int)$this->resizeX > 0 && (int)$this->resizeY > 0 && (int)$this->resizeX < 600 && (int)$this->resizeY < 600)) { $this->resizeX = 90; $this->resizeY = 40; } } |
The getImage method creates an image resource depending on the file extension of the remote image that was provided to the class’ constructor or displays an error if something went south (we do not support the image extension or there was trouble creating the image resource).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | private function getImage() { $ext = array_pop(explode(“.”, $this->file)); if ($ext === “gif”) { $this->img = imagecreatefromgif($this->file); } else if ($ext === “png”) { $this->img = imagecreatefrompng($this->file); } else if ($ext === “jpg” || $ext === “jpeg”) { $this->img = imagecreatefromjpeg($this->file); } else { $this->error = “Unsupported file/image type :(“; } if (!$this->img) { $this->error = “We cannot read this image yet :(“; } } |
The convert method which we are going to call when we want to get the ASCII just gets the image resource and if there was no error – it returns the ASCII HTML code.
1 2 3 4 5 6 7 | public function convert() { $this->getImage(); return $this->error ? $this->error : $this->toAscii(); } |
The actual method (toAscii) which converts the image resource to ASCII first gets the image dimensions and sets them in variables. It then creates a new image resource of the desired or default dimensions with the help of imagecreatetruecolor($w,$h), it resizes the original image in the new resource with the help of imagecopyresampled, and it overrides the original image resource with the new image resource. It then changes the width and height variables to hold the new x and y dimensions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | private function toAscii() { $imgSize = getimagesize($this->file); $width = $imgSize[0]; $height = $imgSize[1]; $newImg = imagecreatetruecolor($this->resizeX, $this->resizeY); imagecopyresampled($newImg, $this->img, 0, 0, 0,0, $this->resizeX, $this->resizeY, $width,$height); $this->img = $newImg; $width = $this->resizeX; $height = $this->resizeY; |
Finally, it creates a pre tag, loops over every pixel of the image and creates a span tag colored after the original pixel’s color with # as content. After every image line, it adds the br tag to add a newline. Then, it just returns the gathered output to the caller.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | $out = “<pre width=’$width’ height=’$height’>”; for ($h = 0; $h < $height;$h++ ) { for ($w = 0; $w < $width;$w++) { $rgb = imagecolorat($this->img, $w,$h); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; $out .= “<span style=’color:rgb($r,$g,$b)’>#</span>”; } $out .=“<br>”; } $out .= “</pre>”; return $out; |
Creating the Image to ASCII service
We are not going to focus on not repeating ourselves for the service and we are just going to write some quick code which shows a front-end to the user. If the user has not submitted our form yet, we just display the form prettified using Bootstrap and a Bootstrap theme. We show an input for URLs and two numeric inputs. Notice the meta viewport tag in the head which enables the site to be responsive for mobile devices.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <?php if (!isset($_REQUEST[‘img’])): ?> <!DOCTYPE html> <html lang=“en”> <head> <meta charset=“UTF-8”> <title>Kewl Image to Ascii Converter</title> <meta name=‘viewport’ content=‘initial-scale=1,width=device-width’> <link rel=“stylesheet” href=‘https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css’> <link rel=“stylesheet” href=‘https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/superhero/bootstrap.min.css’> </head> <body class=“container-fluid col-md-6 col-md-offset-3 col-xs-12 col-sm-10 col-ms-offset-1”> <form > <h1 class=‘text-center’>Convert an arbitrary online image to colored ASCII</h1> <label for=“img”>URL to image</label> <input id=“img” type=“url” class=‘form-control’ name=“img”> <div class=‘col-md-6’> <label for=‘resizeX’>Change Image Width (ASCII can be max 600px)</label> <input value=’90’ class=‘form-control’ type=‘number’ id=‘resizeX’ name=‘resizeX’ placeholder=“Desired Image Width”> </div> <div class=‘col-md-6’> <label for=‘resizeY’>Change Image Height (ASCII can be max 600px)</label> <input value=’40’ class=‘form-control’ type=‘number’ id=‘resizeY’ name=‘resizeY’ placeholder=“Desired Image Height”> </div> <button type=‘submit’ class=‘btn btn-lg btn-success’>Convert to ASCII</button> </form> </body> </html> |
Lastly, if the form was submitted – we convert the image to ASCII, passing the image URL and the desired x and y dimensions (if they were chosen), display the original form and display the ASCII output and the HTML code for the ASCII art in a textarea so that users can copy it and use it in their own website, blog, or another web technology. We also autofill the form with the last query by the user if one exists and escape the user’s input to prevent potential XSS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | <?php else: $resizeX = isset($_REQUEST[‘resizeX’]) ? $_REQUEST[‘resizeX’] : null; $resizeY = isset($_REQUEST[‘resizeY’]) ? $_REQUEST[‘resizeY’] : null; $ascii = new ImageToAscii($_REQUEST[‘img’],$resizeX, $resizeY); $ascii = $ascii->convert(); ?> <html lang=“en”> <head> <meta charset=“UTF-8”> <title>Kewl Image to Ascii Converter</title> <meta name=‘viewport’ content=‘initial-scale=1,width=device-width’> <link rel=“stylesheet” href=‘https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css’> <link rel=“stylesheet” href=‘https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/superhero/bootstrap.min.css’> </head> <body class=“container-fluid col-md-6 col-md-offset-3 col-xs-12 col-sm-10 col-ms-offset-1”> <form> <h1 class=‘text-center’>Convert an arbitrary online image to colored ASCII</h1> <label for=“img”>URL to image</label> <input value=“<?php echo isset($_REQUEST[‘img’]) ? htmlspecialchars($_REQUEST[‘img’]) : “”; ?>“ placeholder=“https://upload.wikimedia.org/wikipedia/en/7/77/EricCartman.png” id=“img” type=“url” class=‘form-control’ name=“img”> <div class=‘col-md-6’> <label for=‘resizeX’>Change Image Width (ASCII can be max 600px)</label> <input value=‘<?php echo isset($_REQUEST[‘resizeX’]) ? htmlspecialchars($_REQUEST[‘resizeX’]) : 90;?>‘ class=‘form-control’ type=‘number’ id=‘resizeX’ name=‘resizeX’ placeholder=“Desired Image Width”> </div> <div class=‘col-md-6’> <label for=‘resizeY’>Change Image Heig (ASCII can be max 600px)</label> <input value=‘<?php echo isset($_REQUEST[‘resizeY’]) ? htmlspecialchars($_REQUEST[‘resizeY’]) : 40;?>‘ class=‘form-control’ type=‘number’ id=‘resizeY’ name=‘resizeY’ placeholder=“Desired Image Height”> </div> <button type=‘submit’ class=‘btn btn-lg btn-success’>Convert to ASCII</button> </form> <?php echo $ascii;?> <label for=“markup”>HTML Code (i.e, to add the ASCII to a page)</label> <textarea class=‘form-control’ id=“markup”><?php echo htmlspecialchars($ascii);?></textarea> <?php endif; ?> |
We did it again. We now are able to convert arbitrary images to ASCII and we are ready to have fun with it. Below is another image converted to ASCII.
Tutorial Categories:
Tutorial Categories:
Thank you very much.
Thank you very much.
Thank you very much.
Thank you very much.