Location: PHPKode > scripts > Boosty's ASCII Artist > boostys-ascii-artist/ASCIIArtist.php
<?php
/**
* ASCIIArtist - Class to convert Bitmap-Images into nice ASCII Texts in HTML format
*
* Copyright (c) 2004, Sebastian Röbke <hide@address.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this 
*   list of conditions and the following disclaimer. 
* - Redistributions in binary form must reproduce the above copyright notice, 
*   this list of conditions and the following disclaimer in the documentation 
*   and/or other materials provided with the distribution. 
* - Neither the name of Sebastian Röbke nor the names of its contributors may be
*   used to endorse or promote products derived from this software without 
*   specific prior written permission. 
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Credits: Florian Schäfer, Maxi Kellner, Andrea Spacca, Alastair Battrick
* Requirements: PHP >= 4.3.x with GD support for the desired image format
* 
* @author   Sebastian Röbke <hide@address.com>
* @version  1.4
* @link     http://www.sebastian-r.de/asciiart/
* @package  ASCIIArtist
* @license  BSD
*/ 

/**
* ASCIIArtist class
*
* @package  ASCIIArtist
*/
class ASCIIArtist
{
    /**
    * The current class version
    * 
    * @var      string
    * @access   private
    * @see      getVersion()
    */
    var $_version = "1.4";
    
    /**
    * Array for error messages
    *
    * @var      array
    * @access   private
    * @see      isError(), getErrors()
    */
    var $_errors = array();
        
    /**
    * The replace characters from dark to light used by render modes 0 and 1 
    * (current version can handle 9 variations)
    *
    * @var      array
    * @access   private
    */
    var $_replaceCharacters = array (
        1 => "W",
        2 => "@",
        3 => "#",
        4 => "*",
        5 => "+",
        6 => ":",
        7 => ".",
        8 => ",",
        9 => "&nbsp;"
    );

    /**
    * Possible image types
    *
    * @var      array
    * @access   private
    */
    var $_imageTypes = array (
        1 => "gif",
        2 => "jpeg",
        3 => "png"
    );

    /**
    * Image resource
    *
    * @var      resource
    * @access   private
    */
    var $_image = 0;
    
    /**
    * Image file height
    *
    * @var      integer
    * @access   private
    */
    var $_imageHeight = 0;
    
    /**
    * Image file height
    *
    * @var      integer
    * @access   private
    */
    var $_imageWidth = 0;
    
    /**
    * Container for the rendered HTML/ASCII image
    *
    * @var      string
    * @access   private
    * @see      getHTMLImage()
    */
    var $_imageHTML = '';
   
    /**
    * CSS for the HTML Image Output
    *
    * @var      string
    * @access   private
    * @see      setImageCSS()
    */
    var $_imageCSS = '
        color               : #000000;
        background-color    : #FFFFFF;
        font-size           : 8px;
        font-family         : "Courier New", Courier, mono;
        line-height         : 5px;
        letter-spacing      : -1px;
    ';
    
    /**
    * CSS for the Error Output
    *
    * @var      string
    * @access   private
    * @see      setErrorCSS()
    */
    var $_errorCSS = '
        text-align          : center;
        color               : #000000;
        background-color    : #EFEFEF;
        font-size           : 11px;
        font-family         : Verdana, Arial, sans-serif;
        border-color        : #333333;
        border-style        : solid;
        border-width        : 1px;
        margin              : 4px;
        padding             : 4px;
    ';
    
    /** 
    * Var to remember the last font tag
    *
    * @var      array
    * @access   private
    */
    var $_lastRGB = array();
    
    /** 
    * Var to remember the font tag state
    *
    * @var      boolean
    * @access   private
    */
    var $_fontTagOpen = false;
    
    /**
    * Returns the hex string of a rgb array
    *
    * Example:
    * $rbg = array("red" -> 255, "green" -> 255, "blue" -> 255); 
    * rgb2hex($rgb) will return "FFFFFF"
    *
    * @param    array   $rgb    An array of red, green and blue values
    * @return   string  The hex values as one string
    * @access   private
    */
    function _RGB2HEX($rgb)
    {
        return sprintf("%02X%02X%02X",$rgb["red"],$rgb["green"],$rgb["blue"]);
    }

    /**
    * Renders the given pixel
    *
    * @param    integer $mode       Current version can handle mode 1, 2 or 3
    * @param    integer $x          X Position of the image
    * @param    integer $y          Y Position of the image
    * @param    string  $fixedChar  Needed for mode 3
    * @access   private
    */
    function _renderPixel($mode, $x, $y, $fixedChar)
    {
        // RGB Value of current pixel (Array)
        $rgb = imagecolorsforindex($this->_image, imagecolorat($this->_image, $x, $y));
        
        // Replace by mode
        switch ($mode) {
            case 1:
                // Rounded Brightness
                $brightness = $rgb["red"] + $rgb["green"] + $rgb["blue"];
        
                // Choose replacing character
                $replaceCharacterNo = round($brightness / 100) + 1;
                
                $this->_imageHTML .= $this->_replaceCharacters[$replaceCharacterNo];
                break;
            case 2:
                // Rounded Brightness
                $brightness = $rgb["red"] + $rgb["green"] + $rgb["blue"];
        
                // Choose replacing character
                $replaceCharacterNo = round($brightness / 100) + 1;

                if ($this->_lastRGB == $rgb) {
                    $this->_imageHTML .= $this->_replaceCharacters[$replaceCharacterNo];
                } else {
                    
                    if ($this->_fontTagOpen) {
                        $this->_imageHTML .= "</font>";
                    }
                    
                    $this->_imageHTML .= "<font color=\"#".$this->_RGB2HEX($rgb)."\">".$this->_replaceCharacters[$replaceCharacterNo];
                    $this->_fontTagOpen = true;
                }
                break;
            case 3:
                if ($this->_lastRGB == $rgb) {
                    $this->_imageHTML .= $fixedChar;
                } else {
                    
                    if ($this->_fontTagOpen) {
                        $this->_imageHTML .= "</font>";
                    }
                    
                    $this->_imageHTML .= "<font color=\"#".$this->_RGB2HEX($rgb)."\">".$fixedChar;
                    $this->_fontTagOpen = true;
                }
                break;

        }
        
        $this->_lastRGB = $rgb;
    }
    
    /**
    * Returns the class version number
    *
    * @return   string  The class version number
    * @access   public
    */
    function getVersion ()
    {
        return $this->_version;
    }
    
    /**
    * Formatting the HTML Image using CSS
    *
    * Tip: Use width-fixed fonts such as Courier only.
    *
    * @param    string    $css    Stylesheet for the image
    * @access   public
    */
    function setImageCSS ($css)
    {
        $this->_imageCSS = $css;
    }
    
    /**
    * Formatting error messages using CSS
    *
    * @param    string    $css    Stylesheet for error message
    * @access   public
    */
    function setErrorCSS ($css)
    {
        $this->_errorCSS = $css;
    }
    
    /**
    * Renders the image into HTML
    *
    * The following modes are implemented: 
    * 1 = black/white using $replaceCharacters by brightness, 
    * 2 = colourized using $replaceCharacters by brightness, 
    * 3 = colourized using a fixed character definded by $fixedChar. 
    * A resolution of 1 means that every pixel is being replaced, 
    * whereas 5 for example means a scanned block of 5 pixel height and width, 
    * resulting in less data to replace.
    *
    * @param    integer $mode       Current version can handle mode 1, 2 or 3
    * @param    integer $resolution Resolution for scanning the bitmap.
    * @param    string  $fixedChar  Needed for mode 3
    * @param    boolean $flipH      Flip output horizontally?
    * @param    boolean $flipV      Flip output vertically?
    * @access   public
    * @see      getHTMLImage()
    */
    function renderHTMLImage($mode = 1, $resolution = 2, $fixedChar = 'W', $flipH = false, $flipV = false)
    {
        $this->_imageHTML = '';
        
        // Minimum value for $resolution is 1
        if ($resolution < 1) {
            $resolution = 1;
        }
        
        // Different loops for flipping
        if (!$flipH && !$flipV) {
            // Y-Axis
            for ($y = 0; $y < $this->_imageHeight; $y += $resolution)
            {
                // X-Axis
                for ($x = 0; $x < $this->_imageWidth; $x += $resolution)
                {
                    $this->_renderPixel($mode, $x, $y, $fixedChar);
                }
                $this->_imageHTML .= "<br>\n";
            }
        }
        else if ($flipH && !$flipV) {
            // Y-Axis
            for ($y = 0; $y < $this->_imageHeight; $y += $resolution)
            {
                // X-Axis
                for ($x = $this->_imageWidth; $x > 0; $x -= $resolution)
                {
                    $this->_renderPixel($mode, $x, $y, $fixedChar);
                }
                $this->_imageHTML .= "<br>\n";
            }
        }
        else if (!$flipH && $flipV) {
            // Y-Axis
            for ($y = $this->_imageHeight; $y > 0; $y -= $resolution)
            {
                // X-Axis
                for ($x = 0; $x < $this->_imageWidth; $x += $resolution)
                {
                    $this->_renderPixel($mode, $x, $y, $fixedChar);
                }
                $this->_imageHTML .= "<br>\n";
            }
        }
        else if ($flipH && $flipV) {
            // Y-Axis
            for ($y = $this->_imageHeight; $y > 0; $y -= $resolution)
            {
                // X-Axis
                for ($x = $this->_imageWidth; $x > 0; $x -= $resolution)
                {
                    $this->_renderPixel($mode, $x, $y, $fixedChar);
                }
                $this->_imageHTML .= "<br>\n";
            }
        }
        if ($this->_fontTagOpen) {
            $this->_imageHTML .= "</font>\n";
        }
    }

    /**
    * Returns the rendered ASCII HTML image and CSS
    *
    * @return   string  The rendered HTML image and CSS
    * @access   public
    */
    function getHTMLImage()
    {
       return '<style type="text/css">'
                .'.asciiimage{'
                .$this->_imageCSS
                .'}</style>'
                .'<span class="asciiimage">'
                .$this->_imageHTML
                .'</span>';
    }
    
    /**
    * Checks if an error has occured
    *
    * @return   boolean
    * @access   public
    * @see      getErrors(), getHTMLErrors()
    */
    function isError()
    {
        return count($this->_errors) > 0;
    }
    
    
    /**
    * Returns the unformatted error messages as an array
    *
    * @return   array   The error messages
    * @access   public
    * @see      isError()
    */
    function getErrors()
    {
        return $this->_errors;
    }
    
    /**
    * Returns the error messages as HTML
    *
    * @return   string  The error messages as HTML
    * @access   public
    * @see      setErrorCSS()
    */
    function getHTMLErrors()
    {
        if (!$this->isError()) {
            return '';
        }
        
        $ret = '<style type="text/css">'
                .'.asciierror{'
                .$this->_errorCSS
                .'}</style>'
                .'<div class="asciierror">';
                
        foreach($this->_errors as $error) {
            $ret.= '<b>Error:</b> '.htmlentities($error).'<br>';
        }
        
        $ret.= '</div>';
        
        return $ret;
    }
    
    /**
    * Tries to set the given bitmap image as source for the ASCII image 
    * and determines width and height
    *
    * If $filename begins with "http://" (not case sensitive), an HTTP 1.0 connection 
    * is opened to the specified server, the page is requested using the HTTP GET method.
    * If filename begins with "ftp://" (not case sensitive), an ftp connection to the 
    * specified server is opened.
    * If the server does not support passive mode ftp, this will fail.
    * If filename is one of "php://stdin", "php://stdout", or "php://stderr",
    * the corresponding stdio stream will be opened.
    * If filename begins with anything else, the file will be opened from the filesystem.
    *
    * @param    string      $filename
    * @return   boolean
    * @access   public
    */
    function setFile($filename)
    {
        if (!$imagesize = getimagesize($filename)) {
            $this->_errors[] = 'Cannot open "'.$filename.'" for reading.';
            return false;
        }
        
        // Create Image from file by type, get and set size
        list($width,$height,$type) = $imagesize;
        switch ($type) {
            case 1:
            case 2:
            case 3:
                $imagefunction = "imagecreatefrom".$this->_imageTypes[$type];
                
                if (!function_exists($imagefunction) || !$this->_image = $imagefunction($filename)) {
                    $this->_errors[] = 'Unable to create images from '.$this->_imageTypes[$type].'. See http://de.php.net/manual/en/ref.image.php for more info.';
                    return false;
                }
                
                $this->_imageHeight = $height;
                $this->_imageWidth  = $width;
                
                break;
            default:
                $this->_errors[] = 'Cannot determine image type of "'.$filename.'".';
                return false;
        }
        
        return true;
    }
    
    /**
    * Returns the height of the original bitmap image in pixels
    *
    * @return   integer
    * @access   public
    */ 
    function getImageHeight()
    {
        return $this->_imageHeight;
    }
    
    /**
    * Returns the width of the original bitmap image in pixels
    *
    * @return   integer
    * @access   public
    */ 
    function getImageWidth()
    {
        return $this->_imageWidth;
    }
}
?>
Return current item: Boosty's ASCII Artist