Image_XBM
[ class tree: Image_XBM ] [ index: Image_XBM ] [ all elements ]

Source for file XBM.php

Documentation is available at XBM.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
  4. // +----------------------------------------------------------------------+
  5. // | PHP version 4                                                        |
  6. // +----------------------------------------------------------------------+
  7. // | Copyright (c) 1997-2002 The PHP Group                                |
  8. // +----------------------------------------------------------------------+
  9. // | This source file is subject to version 2.0 of the PHP license,       |
  10. // | that is bundled with this package in the file LICENSE, and is        |
  11. // | available at through the world-wide-web at                           |
  12. // | http://www.php.net/license/2_02.txt.                                 |
  13. // | If you did not receive a copy of the PHP license and are unable to   |
  14. // | obtain it through the world-wide-web, please send a note to          |
  15. // | license@php.net so we can mail you a copy immediately.               |
  16. // +----------------------------------------------------------------------+
  17. // | Authors: Evgeny Stepanischev <bolk@adme.ru>                          |
  18. // +----------------------------------------------------------------------+
  19. // Project home page (Russian): http://bolk.exler.ru/files/xbm/
  20. //
  21. // $Id$
  22.  
  23. require_once "PEAR.php";
  24.  
  25. /**
  26.  * Black color constant
  27.  */
  28. define ('IMAGE_XBM_BLACK'0);
  29.  
  30. /**
  31.  * White color constant
  32.  */
  33. define ('IMAGE_XBM_WHITE'1);
  34.  
  35. /**
  36.  * Transparency
  37.  */
  38. define ('IMAGE_XBM_TRANS'2);
  39.  
  40. class Image_XBM {
  41.  
  42.    /**
  43.     * Picture width
  44.     *
  45.     * @var integer 
  46.     *
  47.     * @access private
  48.     */
  49.     var $_sx;
  50.  
  51.    /**
  52.     * Picture height
  53.     *
  54.     * @var integer 
  55.     *
  56.     * @access private
  57.     */
  58.     var $_sy;   
  59.  
  60.    /**
  61.     * Picture itself
  62.     *
  63.     * @var array 
  64.     *
  65.     * @access private
  66.     */
  67.     var $_image;
  68.  
  69.    /**
  70.     * Contains style for line drawing
  71.     *
  72.     * @var array 
  73.     *
  74.     * @access private
  75.     */
  76.     var $_style;
  77.  
  78.    /**
  79.     * Position counter in $_style array
  80.     *
  81.     * @var integer 
  82.     *
  83.     * @access private
  84.     */
  85.     var $_stylecnt;
  86.  
  87.     /**
  88.      * Constructor. Init all variables.
  89.      *
  90.      * @access public
  91.      */
  92.     function Image_XBM()
  93.     {
  94.         $this->_sx = 0;
  95.         $this->_sy = 0;
  96.         $this->_image = NULL;
  97.  
  98.         $this->_style = array(1);
  99.         $this->_stylecnt = 0;
  100.  
  101.         if (!defined('IMG_COLOR_STYLED')) {
  102.             define ('IMG_COLOR_STYLED'-1);
  103.         }
  104.     }
  105.  
  106.     /**
  107.      * Create a new image
  108.      *
  109.      * @param int $x_size image width
  110.      * @param int $y_size image height
  111.      * @access public
  112.      * @return bool always true
  113.      */
  114.     function create($x_size$y_size)
  115.     {
  116.         $this->_sx $x_size;
  117.         $this->_sy $y_size;
  118.  
  119.  
  120.         $col array_pad (array()$y_size0);
  121.         $this->_image array_pad (array()ceil($x_size / 8)$col);
  122.  
  123.         return true;
  124.     }
  125.  
  126.     /**
  127.      * Get image width
  128.      *
  129.      * @return int returns the width of the image
  130.      * @access public
  131.      */
  132.     function getWidth()
  133.     {
  134.         return $this->_sx;
  135.     }
  136.  
  137.     /**
  138.      * Get image height
  139.      *
  140.      * @return int returns the height of the image
  141.      * @access public
  142.      */
  143.     function getHeight()
  144.     {
  145.         return $this->_sy;
  146.     }
  147.  
  148.     /**
  149.      * Draw a line
  150.      *
  151.      * @param int $x1 from X
  152.      * @param int $y1 from Y
  153.      * @param int $x2 to X
  154.      * @param int $y2 to Y
  155.      * @param int $color line color
  156.      * @return bool always true
  157.      * @access public
  158.      */
  159.     function drawLine($x1$y1$x2$y2$color)
  160.     {
  161.         $step = 0;
  162.         $dx   abs($x2 $x1);
  163.         $sx   ($x2 $x1> 0 ? 1 : -1;
  164.         $dy   abs($y2 $y1);
  165.         $sy   ($y2 $y1> 0 ? 1 : -1;
  166.  
  167.         if ($dy $dx{
  168.             $step = 1;
  169.             list ($x1$y1= array ($y1$x1);
  170.             list ($dx$dy= array ($dy$dx);
  171.             list ($sx$sy= array ($sy$sx);
  172.         }
  173.  
  174.  
  175.         $e = 2 * $dy $dx;
  176.  
  177.         for ($i = 0; $i $dx; ++$i{
  178.             $step $this->drawPixel ($y1$x1$color:
  179.                     $this->drawPixel ($x1$y1$color);
  180.  
  181.             while ($e >= 0{
  182.                 $y1 += $sy;
  183.                 $e  -= 2 * $dx;
  184.             }
  185.  
  186.             $x1 += $sx;
  187.             $e  += 2 * $dy;
  188.         }
  189.  
  190.         $this->drawPixel ($x2$y2$color);
  191.         return true;
  192.     }
  193.  
  194.     /**
  195.      * Draw a single pixel
  196.      *
  197.      * @param int $x X ordinate
  198.      * @param int $y Y ordinate
  199.      * @param int $color pixel color
  200.      * @return bool always true
  201.      * @access public
  202.      */
  203.     function drawPixel($x$y$color)
  204.     {
  205.         if ($x >= 0 && $y >= 0 && $x $this->_sx && $y $this->_sy && $color <> IMAGE_XBM_TRANS{
  206.  
  207.             if ($color == IMG_COLOR_STYLED{
  208.                 $color $this->_style[$this->_stylecnt++];
  209.  
  210.                 if ($this->_stylecnt >= sizeof($this->_style)) {
  211.                     $this->_stylecnt = 0;
  212.                 }
  213.             }
  214.  
  215.             if ($color{
  216.                 $this->_image[$x >> 3][$y&= 255 ^ (1 << ($x % 8));
  217.             else {
  218.                 $this->_image[$x >> 3][$y|= 1 << ($x % 8);
  219.             }
  220.         }
  221.  
  222.         return true;
  223.     }
  224.  
  225.     /**
  226.      * Get the index of the color of a pixel
  227.      *
  228.      * @param int $x X ordinate
  229.      * @param int $y Y ordinate
  230.      * @return mixed returns color of the pixel or null if pixel out of bounds
  231.      * @access public
  232.      */
  233.     function getColorAt($x$y)
  234.     {
  235.         if ($x >= 0 && $y >= 0 && $x $this->_sx && $y $this->_sy{
  236.             return $this->_image[$x >> 3][$y(1 << ($x % 8)) ? 0 : 1;
  237.         }
  238.  
  239.         return null;
  240.     }
  241.  
  242.     /**
  243.      * Output image to browser or file
  244.      *
  245.      * @param string $filename (optional) filename for output
  246.      * @return bool PEAR_Error or true
  247.      * @access public
  248.      */
  249.     function output($filename = false)
  250.     {
  251.         $wx ceil($this->_sx / 8);
  252.  
  253.         $s "#define _width ".$this->_sx."\n".
  254.              "#define _height ".$this->_sy."\n".
  255.              "static unsigned char _bits[] = {\n";
  256.  
  257.         for ($y = 0; $y $this->_sy; ++$y{
  258.             for ($x = 0; $x $wx; ++$x{
  259.                 $s .= '0x'.sprintf('%02x'$this->_image[$x][$y]).', ';
  260.             }
  261.         }
  262.  
  263.         $s rtrim ($s', ')."\n}";
  264.  
  265.         if ($filename === false{
  266.             echo $s;
  267.         else {
  268.             if ($fp fopen($filename'w')) {
  269.                 flock($fpLOCK_EX);
  270.  
  271.                 fwrite($fp$s);
  272.                 fclose($fp);
  273.             else {
  274.                 return PEAR::raiseError('Cannot open file for writting.'5);
  275.             }
  276.         }
  277.  
  278.         return true;
  279.     }
  280.  
  281.     /**
  282.      * Draw a rectangle
  283.      *
  284.      * @param int $x1 left coordinate
  285.      * @param int $y1 top coordinate
  286.      * @param int $x2 right coordinate
  287.      * @param int $y2 bottom coordinate
  288.      * @param int $color drawing color
  289.      * @return bool always true
  290.      * @access public
  291.      */
  292.     function drawRectangle($x1$y1$x2$y2$color)
  293.     {
  294.         $this->drawline ($x1$y1$x2$y1$color);
  295.         $this->drawline ($x2$y1$x2$y2$color);
  296.         $this->drawline ($x2$y2$x1$y2$color);
  297.         $this->drawline ($x1$y2$x1$y1$color);
  298.  
  299.         return true;
  300.     }
  301.  
  302.     /**
  303.      * Draw a filled rectangle
  304.      *
  305.      * @param int $x1 left coordinate
  306.      * @param int $y1 top coordinate
  307.      * @param int $x2 right coordinate
  308.      * @param int $y2 bottom coordinate
  309.      * @param int $color drawing color
  310.      * @return bool always true
  311.      * @access public
  312.      */
  313.     function drawFilledRectangle($x1$y1$x2$y2$color)
  314.     {
  315.         $hx min(max($x1$x2)$this->_sx - 1);
  316.         $lx max(min($x1$x2)0);
  317.  
  318.         for ($x $lx$x <= $hx; ++$x{
  319.             $this->drawline ($x$y1$x$y2$color);
  320.         }
  321.  
  322.         return true;
  323.     }
  324.  
  325.     /**
  326.      * Draw a polygon
  327.      *
  328.      * @param array $points is a PHP array containing the polygon's vertices
  329.      * @param int $num_points is the total number of points (vertices).
  330.      * @param int $color drawing color
  331.      * @return bool always true
  332.      * @access public
  333.      */
  334.     function drawPolygon($points$num_points$color)
  335.     {
  336.         if ($num_points > 2{
  337.             for ($i = 0; $i<$num_points - 1; ++$i{
  338.                 $j $i * 2;
  339.  
  340.                 $this->drawline($points[$j]$points[$j+1]$points[$j+2]$points[$j+3]$color);
  341.             }
  342.  
  343.             $this->drawline($points[0]$points[1]$points[$num_points * 2 - 2]$points[$num_points * 2 - 1]$color);
  344.         }
  345.  
  346.         return true;
  347.     }
  348.  
  349.     /**
  350.      * Destroy an image
  351.      *
  352.      * @return bool always true
  353.      * @access public
  354.      */
  355.     function destroy()
  356.     {
  357.         $this->Image_XBM();
  358.         return true;
  359.     }
  360.  
  361.     /**
  362.      * Sets the style to be used by all line drawing functions
  363.      * (such as imageline() and imagepolygon()) when drawing
  364.      * with the special color IMG_COLOR_STYLED
  365.      *
  366.      * @param array $style is an array of pixels.
  367.      * @return bool always true
  368.      * @access public
  369.      */
  370.     function setStyle($style)
  371.     {
  372.         if (!is_array($style)) {
  373.             $style = array($style);
  374.         }
  375.  
  376.         $this->_style $style;
  377.         return true;
  378.     }
  379.  
  380.     /**
  381.      * Flood fill
  382.      *
  383.      * @param int $x starting coordinate
  384.      * @param int $y starting coordinate
  385.      * @param int $color color
  386.      * @return bool always true
  387.      * @access public
  388.      */
  389.     function fill($x$y$color)
  390.     {
  391.         $color $color ? 1 : 0;
  392.  
  393.         $stack = array(array($x$y));
  394.  
  395.         while (sizeof($stack)) {
  396.             list ($x$yarray_pop($stack);
  397.  
  398.             if ($this->getColorAt($x$y<> $color{
  399.                     $this->drawPixel($x$y$color);
  400.             }
  401.  
  402.             if (($px $this->getColorAt($sx $x + 1$y)) <> $color && $px !== null{
  403.                 $stack[= array($sx$y);
  404.             }
  405.  
  406.             if (($px $this->getColorAt($x$sy $y + 1)) <> $color && $px !== null{
  407.                 $stack[= array($x$sy);
  408.             }
  409.  
  410.             if (($px $this->getColorAt($sx $x - 1$y)) <> $color && $px !== null{
  411.                 $stack[= array($sx$y);
  412.             }
  413.  
  414.             if (($px $this->getColorAt($x$sy $y - 1)) <> $color && $px !== null{
  415.                 $stack[= array($x$sy);
  416.             }
  417.         }
  418.  
  419.         return true;
  420.     }
  421.  
  422.     /**
  423.      * Copy part of an image
  424.      *
  425.      * @param object $src_im destination Image_XBM object
  426.      * @param int $dst_x starting x coordinate in the destination
  427.      * @param int $dst_y starting y coordinate in the destination
  428.      * @param int $src_x starting x coordinate in the source
  429.      * @param int $src_y starting y coordinate in the source
  430.      * @param int $src_w width of portion
  431.      * @param int $src_h height of portion
  432.      * @return bool always true
  433.      * @access public
  434.      */
  435.     function copy(&$src_im$dst_x$dst_y$src_x$src_y$src_w$src_h)
  436.     {
  437.         // If pictures are equals then just copy
  438.         if (!$dst_x && !$dst_y && $src_w == $this->_sx - 1 &&
  439.         $src_h == $this->_sy - 1 && $src_im->_sx == $this->_sx &&
  440.         $src_im->_sy == $this->_sy{
  441.             $this->_image $src_im->_image;
  442.             return true;
  443.         }
  444.  
  445.         // Fast copy
  446.         if ($src_x % 8 == $dst_x % 8{
  447.             $stop_x  ($src_w >> 3* 8;
  448.             $start_x $src_x % 8;
  449.  
  450.             $src_h min($src_h$this->_sy $dst_y - 1$src_im->_sy - $src_y - 1);
  451.             $src_w min($src_w$this->_sx $dst_x - 1$src_im->_sx - $src_x - 1);
  452.  
  453.             for ($j = 0; $j $src_h; ++$j{
  454.                 for ($i = 0; $i $src_w; ++$i{
  455.                     if ($i $start_x || $i >= $stop_x{
  456.                         $this->drawPixel($dst_x $i$dst_y $j$src_im->getColorAt($src_x $i$src_y $j));
  457.                     else {                                    
  458.                         $this->_image[($i+$dst_x>> 3][$dst_y $j$src_im->_image[($i $src_x>> 3][$src_y $j];
  459.                         $i += 7;
  460.                     }
  461.                 }
  462.             }
  463.  
  464.             return true;
  465.         }
  466.  
  467.         // Slow copy
  468.         for ($i = 0; $i $src_w; ++$i{
  469.             for ($j = 0; $j $src_h; ++$j{
  470.                 $this->drawPixel($dst_x $i$dst_y $j$src_im->getColorAt($src_x $i$src_y $j));
  471.             }
  472.         }
  473.  
  474.         return true;
  475.     }
  476.  
  477.     /**
  478.      * Create a new image from XBM file or URL
  479.      *
  480.      * @param string $filename XBM file name or URL
  481.      * @return mixed PEAR_error or true for success
  482.      * @access public
  483.      */
  484.     function createFromFile($filename)
  485.     {
  486.         $fp fopen($filename'r');
  487.         if (!is_resource($fp)) {
  488.             return PEAR::raiseError('Cannot open file.'4);
  489.         }
  490.  
  491.         for ($i = 0; $i < 2; ++$i{
  492.             if (feof($fp)) {
  493.                 fclose($fp);
  494.                 return PEAR::raiseError('Invalid XBM file.'5);
  495.             }
  496.  
  497.             $line fgets($fp1024);
  498.             if (preg_match('/^#define\s+.*?_(width|height)\s+(\d+)/'$line$match)) {
  499.                 ${$match[1]$match[2];
  500.             }
  501.         }
  502.  
  503.         if (feof($fp|| !isset($width|| !isset($height)) {
  504.             fclose($fp);
  505.             return PEAR::raiseError('Invalid XBM file.'5);
  506.         }
  507.  
  508.         $picture preg_replace('/^\s*static\s+(?:unsigned\s+)char\s+.*?_bits\[\]\s*=\s*\{/'''fread($fp@filesize($filename)));
  509.         $picture preg_replace('/\s*\};?\s*$/'''$picture);
  510.  
  511.         $this->create($width$height);
  512.         $picture explode(','$picture);
  513.         $sx ceil($width / 8);
  514.  
  515.         for ($s $j = 0; $j $height; ++$j{
  516.             for ($i = 0; $i $sx; ++$i{
  517.                 $this->_image[$i][$jhexdec($picture[$s++]);
  518.             }
  519.         }
  520.  
  521.         fclose($fp);
  522.  
  523.         return true;
  524.     }
  525.  
  526.     /**
  527.      * Draw an ellipse
  528.      *
  529.      * @param int $cx center of ellipse (X coordinate)
  530.      * @param int $cy center of ellipse (Y coordinate)
  531.      * @param int $w width of ellipse
  532.      * @param int $h height of ellipse
  533.      * @param int $color color for drawing
  534.      * @return bool always true
  535.      * @access public
  536.      */
  537.     function drawEllipse($cx$cy$w$h$color)
  538.     {
  539.         return $this->_ellipse($cx$cy$w$h$color);
  540.     }
  541.  
  542.     /**
  543.      * Draw a filled ellipse
  544.      *
  545.      * @param int $cx center of ellipse (X coordinate)
  546.      * @param int $cy center of ellipse (Y coordinate)
  547.      * @param int $w width of ellipse
  548.      * @param int $h height of ellipse
  549.      * @param int $color color for drawing
  550.      * @return bool always true
  551.      * @access public
  552.      */
  553.     function drawFilledEllipse($cx$cy$w$h$color)
  554.     {
  555.         return $this->_ellipse($cx$cy$w$h$colortrue);
  556.     }
  557.  
  558.     /**
  559.      * To draw a text string over an image using Figlet fonts
  560.      *
  561.      * @param string $text text for drawing
  562.      * @param string $font font file name
  563.      * @param mixed $size integer (font ratio) or string 'X:Y' (X size ratio and Y size ratio)
  564.      * @param int $fgcolor foreground font color
  565.      * @param int $bgcolor background font color
  566.      * @param int $x start drawing from
  567.      * @param int $y start drawing from
  568.      * @return mixed PEAR_error or true for success
  569.      * @access public
  570.      */
  571.     function drawFigletText($text$font$size$fgcolor$bgcolor$x$y)
  572.     {
  573.         if (is_numeric($size)) {
  574.             $x_ratio $y_ratio $size;
  575.         else {
  576.             @list($x_ratio$y_ratiopreg_split('/[:x]/'$size2);
  577.         }
  578.  
  579.         if (!$x_ratio || !$y_ratio{
  580.             return PEAR::raiseError('Invalid font ratio.'3);
  581.         }
  582.  
  583.         require_once 'Text/Figlet.php';
  584.         $figlet &new Text_Figlet();
  585.  
  586.         if (PEAR::isError($error $figlet->LoadFont($font))) {
  587.             return PEAR::raiseError('Font loading error.'2);
  588.         }
  589.  
  590.         $lines explode("\n"$figlet->lineEcho($text));
  591.         $cnt   sizeof($lines);
  592.  
  593.         for ($i = 0; $i $cnt; ++$i{
  594.             for ($j = 0; $j strlen($lines[$i]); ++$j{
  595.                 $c $lines[$i]{$j<> ' ' $fgcolor $bgcolor;
  596.  
  597.                 for ($rx = 0; $rx $x_ratio; ++$rx{
  598.                     for ($ry = 0; $ry $y_ratio; ++$ry{
  599.                         $this->drawPixel($x $j $x_ratio $rx$y $i $y_ratio $ry$c);
  600.                     }
  601.                 }
  602.             }
  603.         }
  604.  
  605.         return true;
  606.     }
  607.  
  608.     /**
  609.      * Draw a ellipse
  610.      *
  611.      * @param int $x center of ellipse (X coordinate)
  612.      * @param int $y center of ellipse (Y coordinate)
  613.      * @param int $a width of ellipse
  614.      * @param int $b height of ellipse
  615.      * @param int $color color for drawing
  616.      * @param bool $filled (optional) filled ellipse or not
  617.      * @return bool always true
  618.      * @access private
  619.      */
  620.     function _ellipse($x$y$a$b$color$filled = false)
  621.     {
  622.         $a_square $a $a;
  623.         $b_square $b $b;
  624.  
  625.         $row $b;
  626.         $col = 0;
  627.         $two_a_square  $a_square << 1;
  628.         $four_a_square $a_square << 2;
  629.         $two_b_square  $b_square << 1; 
  630.         $four_b_square $b_square << 2;
  631.  
  632.         $d $two_a_square*(($row - 1$row$a_square $two_b_square (1 - $a_square);
  633.         while ($a_square $row $b_square $col{
  634.             if ($filled{
  635.                 $this->drawline($col $x$row $y$col $x$y $row$color);
  636.                 $this->drawline($x $col$row $y$x $col$y $row$color);
  637.             else {
  638.                 $this->drawPixel($col $x$row $y$color);
  639.                 $this->drawPixel($col $x$y $row$color);
  640.                 $this->drawPixel($x $col$row $y$color);
  641.                 $this->drawPixel($x $col$y $row$color);
  642.             }
  643.  
  644.             if ($d >= 0{
  645.                 $row--; 
  646.                 $d -= $four_a_square*$row
  647.             }
  648.  
  649.             $d += $two_b_square*(3 + ($col << 1))
  650.             ++$col
  651.         }
  652.  
  653.         $d $two_b_square ($col + 1$col $two_a_square *
  654.         ($row ($row - 2+ 1(1 - $two_a_square$b_square;
  655.  
  656.         while ($row + 1{
  657.             if ($filled{
  658.                 $this->drawline($col $x$row $y$col $x$y $row$color);
  659.                 $this->drawline($x $col$row $y$x $col$y $row$color);
  660.             else {
  661.                 $this->drawPixel($col $x$row $y$color);
  662.                 $this->drawPixel($col $x$y $row$color);
  663.                 $this->drawPixel($x $col$row $y$color);
  664.                 $this->drawPixel($x $col$y $row$color);
  665.             }
  666.  
  667.             if ($d <= 0{
  668.                 ++$col;
  669.                 $d += $four_b_square $col;
  670.             }
  671.  
  672.             $row--; 
  673.             $d += $two_a_square (3 - ($row << 1));
  674.         }
  675.  
  676.         return true;
  677.     }
  678. }
  679. ?>

Documentation generated on Mon, 11 Mar 2019 14:28:41 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.