<?php

require_once dirname(__FILE__) . '/../Image.php';

/**
 * This class implements the Horde_Image:: API for ImageMagick.
 *
 * $Horde: horde/lib/Image/im.php,v 1.18 2003/07/26 23:01:43 chuck Exp $
 *
 * Copyright 2002-2003 Chuck Hagenbuch <chuck@horde.org>
 * Copyright 2003 Mike Cochrane <mike@graftonhall.co.nz>
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @author  Mike Cochrane <mike@graftonhall.co.nz>
 * @version $Revision: 1.18 $
 * @since   Horde 3.0
 * @package Horde_Image
 */
class Horde_Image_im extends Horde_Image {

    /**
     * Capabilites of this driver.
     * @var array $_capabilities
     */
    var $_capabilities = array('resize',
                               'rotate',
                               'grayscale',
                               'flip',
                               'mirror',
                               'sepia',
                               'canvas'
                         );

    /**
     * Operations to be performed.
     * @var array $_operations
     */
    var $_operations = array();

    /**
     * Constructor.
     */
    function Horde_Image_im($params)
    {
        if (isset($params['width'])) {
            $this->_width = $params['width'];
        }
        if (isset($params['width'])) {
            $this->_height = $params['height'];
        }
    }

    /**
     * Return the content type for this image.
     *
     * @return string  The content type for this image.
     */
    function getContentType()
    {
        return 'image/jpeg';
    }

    /**
     * Display the current image.
     */
    function display()
    {
        $this->headers();
        echo $this->raw();
    }

    /**
     * Return the raw data for this image.
     *
     * @return string The raw image data.
     */
    function raw()
    {
        global $conf;

        if (!empty($this->_data)) {
            $tmpin = $this->toFile();
        } else {
            // Create a dump PPM file to load.
            $tmpin = Horde::getTempFile('img', false);
            $fp = fopen($tmpin, 'wb');
            fwrite($fp, sprintf("P3\n%d %d\n255\n ", $this->_width, $this->_height));
            fclose($fp);
        }

        $command = '' . $conf['utils']['convert'];
        $command .= " \"$tmpin\" ";

        $command .= implode(' ', $this->_operations);
        $tmpout = Horde::getTempFile('img', false);
        $command .= " +profile \"*\" jpeg:\"$tmpout\"";

        exec($command);

        $fp = fopen($tmpout, 'r');
        $this->_data = fread($fp, filesize($tmpout));
        fclose($fp);

        @unlink($tmpin);
        unlink($tmpout);

        return $this->_data;
    }

    /**
     * Resize an image.
     *
     * @param integer $width   The new width.
     * @param integer $height  The new height.
     * @param boolean $ratio   Maintain original aspect ratio.
     */
    function resize($width, $height, $ratio = true)
    {
        if ($ratio) {
            $this->_operations[] = "-resize {$width}x{$height}";
        } else {
            $this->_operations[] = "-resize {$width}x{$height}!";
        }
    }

    /**
     * Rotate an image.
     *
     * @param integer $angle       The angle to rotate the image by,
     *                             in the clockwise direction.
     * @param integer $background  The background color to fill any triangles.
     */
    function rotate($angle, $background = 'white')
    {
        $this->_operations[] = "-rotate {$angle} -background $background";
    }

    /**
     * Flip an image.
     */
    function flip()
    {
        $this->_operations[] = "-flip";
    }

    /**
     * Mirror an image.
     */
    function mirror()
    {
        $this->_operations[] = "-flop";
    }

    /**
     * Convert an image to grayscale.
     */
    function grayscale()
    {
        $this->_operations[] = "-colorspace GRAY -colors 256";
    }

    /**
     * Sepia filter.
     */
    function sepia()
    {
        $this->_operations[] = "-modulate 110 -colorspace GRAY -colors 256 -gamma 1.25/1/0.66";
    }

    /**
     * Draws a text string on the image in a specified location, with
     * the specified style information.
     *
     * @param string  $text       The text to draw.
     * @param integer $x          The left x coordinate of the start of the text string.
     * @param integer $y          The top y coordinate of the start of the text string.
     * @param string  $font       The font identifier you want to use for the text.
     * @param string  $color      The color that you want the text displayed in.
     * @param integer $direction  An integer that specifies the orientation of the text.
     */
    function text($string, $x, $y, $font = '_sans', $color = 'black', $direction = 0)
    {
    }

    /**
     * Draw a circle.
     *
     * @param integer $x      The x co-ordinate of the centre.
     * @param integer $y      The y co-ordinate of the centre.
     * @param integer $r      The radius of the circle.
     * @param string  $color  The line color of the circle.
     * @param string  $fill   (optional) The color to fill the circle.
     */
    function circle($x, $y, $r, $color, $fill = 'none')
    {
        $xMax = $x + $r;
        $yMax = $y + $r;
        $this->_operations[] = "-stroke $color";
        $this->_operations[] = "-fill $fill";
        $this->_operations[] = "-draw \"circle $x,$y $xMax,$yMax\"";
    }

    /**
     * Draw a polygon based on a set of vertices.
     *
     * @param array   $vertices  An array of x and y labeled arrays
     *                           (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
     * @param string  $color     The color you want to draw the polygon with.
     * @param string  $fill      (optional) The color to fill the polygon.
     */
    function polygon($verts, $color, $fill = 'none')
    {
        $command = '';
        foreach ($verts as $vert) {
            $command .= sprintf(" %d,%d", $vert['x'], $vert['y']);
        }
        $this->_operations[] = "-stroke $color";
        if (!empty($fill)) {
            $this->_operations[] = "-fill $fill";
        } else {
            $this->_operations[] = "-fill none";
        }

        $this->_operations[] = "-draw \"polygon $command\"";
    }

    /**
     * Draw a rectangle.
     *
     * @param integer $x       The left x-coordinate of the rectangle.
     * @param integer $y       The top y-coordinate of the rectangle.
     * @param integer $width   The width of the rectangle.
     * @param integer $height  The height of the rectangle.
     * @param string  $color   The line color of the rectangle.
     * @param string  $fill    (optional) The color to fill the rectangle.
     */
    function rectangle($x, $y, $width, $height, $color, $fill = 'none')
    {
        $xMax = $x + $width;
        $yMax = $y + $height;
        $this->_operations[] = "-stroke $color";
        $this->_operations[] = "-fill $fill";
        $this->_operations[] = "-draw \"rectangle $x,$y $xMax,$yMax\"";
    }

    /**
     * Draw a line.
     *
     * @param integer $x0     The x co-ordinate of the start.
     * @param integer $y0     The y co-ordinate of the start.
     * @param integer $x1     The x co-ordinate of the end.
     * @param integer $y1     The y co-ordinate of the end.
     * @param string  $color  (optional) The line color.
     * @param string  $width  (optional) The width of the line.
     */
    function line($x0, $y0, $x1, $y1, $color = 'black', $width = 1)
    {
        $this->_operations[] = "-stroke $color";
        $this->_operations[] = "-strokewidth $width";
        $this->_operations[] = "-draw \"line $x0,$y0 $x1,$y1\"";
    }

    /**
     * Draw a polyline (a non-closed, non-filled polygon) based on a
     * set of vertices.
     *
     * @param array   $vertices  An array of x and y labeled arrays
     *                           (eg. $vertices[0]['x'], $vertices[0]['y'], ...).
     * @param string  $color     The color you want to draw the line with.
     * @param string  $width     (optional) The width of the line.
     */
    function polyline($verts, $color, $width = 1)
    {
        $command = '';
        foreach ($verts as $vert) {
            $command .= sprintf(" %d,%d", $vert['x'], $vert['y']);
        }
        $this->_operations[] = "-stroke $color";
        $this->_operations[] = "-draw \"polyline $command\"";
    }

    /**
     * Draw an arc.
     *
     * @param integer $x      The x co-ordinate of the centre.
     * @param integer $y      The y co-ordinate of the centre.
     * @param integer $r      The radius of the arc.
     * @param integer $start  The start angle of the arc.
     * @param integer $end    The end angle of the arc.
     * @param string  $color  The line color of the arc.
     * @param string  $fill   The fill color of the arc (defaults to none).
     */
    function arc($x, $y, $r, $start, $end, $color = 'black', $fill = null)
    {
        $xMax = $x + $r;
        $yMax = $y + $r;
        $this->_operations[] = "-stroke $color";
        $this->_operations[] = '-fill ' . (!empty($fill) ? $fill : 'none');
        $this->_operations[] = "-draw \"ellipse $x,$y $xMax,$yMax $start,$end\"";
    }

}
