<?php
/* SVN FILE: $Id: ImageMagick.php 182 2008-04-26 17:18:59Z bb_yujiro $ */
/**
 *  ImageMagickによる画像処理
 *
 * 注意事項:
 *      ImageMagickを使用しています。以下などから取り寄せてください。
 *      http://www.imagemagick.org/script/download.php
 *
 * PHP versions 5
 *
 *      hitSuji : Social Network Service <http://rakuto.net/rktSNS/>
 *      Copyright (c) 2007 Yujiro Takahashi
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 182 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-04-27 02:18:59 +0900 (日, 27 4 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */

if (!defined('IMAGEMAGICK_PATH')){
    define('IMAGEMAGICK_PATH','/usr/local/bin/');
}
if (!defined('ERROR_LOG_FILE')){
    define('ERROR_LOG_FILE','error.log');
}

/**
 *  ImageMagick操作クラス
 *
 * @category        Image
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 182 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-04-27 02:18:59 +0900 (日, 27 4 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */ 
class Image_ImageMagick
{
    /**
     * 画像のバイナリ情報
     * @var binary
     */
    public $buffer = null;

    /**
     * 画像ファイル名
     * @var string
     */
    private $_filename = '';

    /**
     * 画像タイプ
     * @var string
     */
    private $_type = null;

    /**
     * フォーマット
     * @var string
     */
    private $_format = null;

    /**
     * 画像名
     * @var string
     */
    private $_name = null;

    /**
     * 幅
     * @var integer
     */
    private $_width = null;

    /**
     * 高さ
     * @var integer
     */
    private $_height = null;

    /**
     * 描画の色
     * @var string
     */
    private $_fill_color = 'white';

    /**
     * 線の色
     * @var string
     */
    private $_stroke_color = 'black';

    /**
     * フォントの大きさ
     * @var integer
     */
    private $_pointsize = 10;

    /**
     * 線の太さ
     * @var integer
     */
    private $_stroke_width = 1;

    /**
     * フォントのファイル名
     * @var strong
     */
    private $_font = '';

    /**
     * コンストラクタ
     *
     * @access public
     * @param string $source
     * @return void
     */
    public function __construct($filename=null)
    {
        if (empty($filename)){
            return ;
        }

        $this->_filename = $filename;
        $this->readImage($this->_filename);
    }

    /**
     * 画像情報をバッファに格納
     *
     * @access private
     * @return boolean
     */
    public function readImage($filename)
    {
        $this->_filename = $filename;
        if (!file_exists ($this->_filename)){
            return false;
        }
        $this->_setInfo();

        /* ファイルの中身を取得 */
        $handle = fopen($this->_filename, 'rb');
        if (!is_resource($handle)) {
            return false;
        }
        $this->buffer = fread($handle, filesize($this->_filename));
        fclose($handle);
        
        return true;
    }

    /**
     * コマンドの直接実行
     *
     * @access public
     * @param string $command コマンド名
     * @param string $param パラメータ
     * @return boolean
     */
    public function direct($command, $param)
    {
        $command = '"'.IMAGEMAGICK_PATH.$command.'" '.$param.' '.$this->_filename;
        ob_start();
        passthru($command);
        $result = ob_get_contents();
        ob_end_clean();

        return $result;
    }

    /**
     * コマンドの実行
     *
     * @access public
     * @param string $command コマンド名
     * @param string $param パラメータ
     * @return boolean
     */
    public function command($command, $param)
    {
        $command = '"'.IMAGEMAGICK_PATH.$command.'" '.$param;
        $inout = substr_count($param, ':-'); 

        $descriptorspec = array(
            0 => array('pipe', 'r'),
            1 => array('pipe', 'w'),
            2 => array('file', ERROR_LOG_FILE, 'a')
        );
        $pipes = array();
        $process = proc_open($command, $descriptorspec, $pipes);
        if (!is_resource($process)) {
            return false;
        }
        if ($inout == 2){
            fwrite($pipes[0], $this->buffer);
            fclose($pipes[0]);
        }

        ob_start();
        fpassthru($pipes[1]);
        $this->buffer = ob_get_contents();
        ob_end_clean();

        fclose($pipes[1]);
        proc_close($process);

        return true;
    }

    /**
     * identifyの実行
     *
     * @access public
     * @param string $param パラメータ
     * @return boolean
     */
    public function identify($param)
    {
        if (empty($this->buffer)){
            return false;
        }

        $command = '"'.IMAGEMAGICK_PATH.'identify" '.$param;
        $descriptorspec = array(
            0 => array('pipe', 'r'),
            1 => array('pipe', 'w'),
            2 => array('file', ERROR_LOG_FILE, 'a')
        );
        $pipes = array();
        $process = proc_open($command, $descriptorspec, $pipes);
        if (!is_resource($process)) {
            return false;
        }
        $res = fwrite($pipes[0], $this->buffer);
        fclose($pipes[0]);

        $result = fread($pipes[1], 8192);

        fclose($pipes[1]);
        proc_close($process);

        return $result;
    }

    /**
     * 画像情報の取得
     *
     * @access private
     * @return void
     */
    public function _setInfo()
    {
        $format = array(
            'so'=>  '"%m:%f:%w:%h;"',
            'dll'=> '%m:%f:%w:%h;',
        );
        $param  = '-format ';
        $param .= $format[PHP_SHLIB_SUFFIX].' ';
        
        if (empty($this->_format)){
            $result = $this->direct('identify', $param);
        } else {
            $param .= $this->_format.':-';
            $result = $this->identify($param);
        }
        $row = explode(';', $result);

        if (empty($row[0])){
            $this->info = array('error'=>1);
            return ;
        }
        $info = explode(':', $row[0]);

        $this->_type   = $info[0];
        $this->_format = strtolower($info[0]);
        $this->_name   = $info[1];
        $this->_width  = $info[2];
        $this->_height = $info[3];
    }

    /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
          basic
      _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/

    /**
     * 対象画像の出力
     *
     * @access public
     * @return void
     */
    public function output($filename=null)
    {
        if (empty($filename)){
            $type = $this->_format;
            $type = preg_replace('/jpg/i','jpeg',$type);
            header('Content-Type: image/'.$type);
            header('Content-Length: '.strlen($this->buffer));
            header('Content-disposition: inline; filename='.$this->_name);

            echo $this->buffer;
        } else {
            $this->save($filename);
        }
    }

    /**
     * 対象画像の保存
     *
     * @access public
     * @param string $filename 画像のファイル名
     * @return boolean
     */
    public function save($filename)
    {
        /* ファイルの中身を取得 */
        $handle = fopen($filename, 'wb');
        if (!is_resource($handle)) {
            return false;
        }
        $result = fwrite($handle, $this->buffer);
        fclose($handle);
        
        return $result;
    }

    /**
     * 画像情報の取得
     *
     * @access public
     * @return array 画像情報
     */
    public function getInfo()
    {
        $this->_setInfo();

        return array(
            'type'=>   $this->_type,
            'format'=> $this->_format,
            'name'=>   $this->_name,
            'width'=>  $this->_width,
            'height'=> $this->_height,
        );
    }

    /**
     * 画像バイナリデータの取得
     *
     * @access public
     * @return binary
     */
    public function getBinary()
    {
        return $this->buffer;
    }

    /**
     * 対象画像フォーマットの変換
     *
     * @access public
     * @param string $format 変換する画像フォーマット
     * @return boolean
     */
    public function convert($format)
    {
        $format = empty($format)?$this->_format:$format;        
        $command = 'convert';
        $param  = $this->_format.':- '.$format.':-';

        $this->_type = $format;
        $this->_format = $format;
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像フォーマットの変換
     *
     * @access public
     * @param integer $width 画像の幅
     * @param integer $height 画像の高さ
     * @param string $color 背景色
     * @param string $format フォーマット
     * @return boolean
     */
    public function create($width, $height, $color='white', $format='gif')
    {
        $command = 'convert';

        $param  = '-size ';
        $param .= $width.'x'.$height.' ';
        $param .= 'xc:';
        $param .= $color.' ';
        $param .= $format.':-';

        $this->_type   = $format;
        $this->_format = strtolower($format);
        $this->_name   = 'none.'.$this->_format;
        $this->_width  = $width;
        $this->_height = $height;
        
        return $this->command($command, $param);
    }

    /**
     * 画像バイナリデータの設定
     *
     * @access public
     * @param binary $binary 画像バイナリデータ
     * @param string $format フォーマット
     * @return boolean
     */
    public function setBinary($binary, $format)
    {
        $this->_type   = $format;
        $this->_format = strtolower($format);
        $this->_name   = 'none.'.$this->_format;
        $this->_width  = 0;
        $this->_height = 0;

        $this->buffer = $binary;
        $this->_setInfo();

        return true;
    }

    /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
          move px
      _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/

    /**
     * アニメーション画像
     *
     * @access public
     * @param mixed $filename ファイル名
     * @param integer $delay 切替速度
     * @param integer $loop 繰り返し回数(ms)
     * @return boolean
     */
    public function animated($filename, $delay=100, $loop=0)
    {
        if (is_array($filename)){
            $filename = implode(' ', $filename); 
        }
        $command = 'convert';

        $param  = '-delay ';
        $param .= $delay.' ';
        $param .= '-loop ';
        $param .= $loop.' ';

        $param .= $filename.' ';
        $param .= 'gif:-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像を切り取る
     *
     * @access public
     * @param integer $width 画像の幅
     * @param integer $height 画像の高さ
     * @param integer $x x軸の移動ピクセル
     * @param integer $y y軸の移動ピクセル
     * @return boolean
     */
    public function crop($width, $height, $x=0, $y=0)
    {        
        $command = 'convert';

        $param  = '-crop ';
        $param .= $width.'x'.$height;
        $param .= '+'.$x.'+'.$y.' ';
        $param .= $this->_format.':- '.$this->_format.':-';

        $this->_width  = $width;
        $this->_height = $height;
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の中央引き寄せ
     *
     * @access public
     * @param integer $factor 要素
     * @return boolean
     */
    public function implode($factor)
    {        
        $command = 'convert';

        $param  = '-implode ';
        $param .= $factor.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のリサイズ
     *
     * @access public
     * @param integer $width   画像の幅
     * @param integer $height  画像の高さ
     * @param boolean $exactly 指定サイズを厳守(縦横比無視)
     * @return boolean
     */
    public function resize($width, $height, $exactly=false)
    {
        if ($this->_width < $width &&
            $this->_height < $height && !$exactly){
            return ;
        }

        $exactly = ($exactly)?'!':'';
        
        $command = 'convert';

        $param  = '-resize ';
        $param .= $width.'x'.$height.$exactly.' ';
        $param .= $this->_format.':- '.$this->_format.':-';

        $this->_width  = $width;
        $this->_height = $height;
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像を巻き込み
     *
     * @access public
     * @param integer $x x軸の移動ピクセル
     * @param integer $y y軸の移動ピクセル
     * @return boolean
     */
    public function roll($x, $y)
    {        
        $command = 'convert';

        $param  = '-roll ';
        $param .= '+'.$x.'+'.$y.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の回転
     *
     * @access public
     * @param integer $angle 回転角度
     * @return boolean
     */
    public function rotate($angle)
    {        
        $command = 'convert';

        $param  = '-rotate ';
        $param .= $angle.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の傾き
     *
     * @access public
     * @param integer $x x軸の角度
     * @param integer $y y軸の角度
     * @return boolean
     */
    public function shear($x, $y)
    {        
        $command = 'convert';

        $param  = '-shear ';
        $param .= $x.'x'.$y.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の渦巻き表示
     *
     * @access public
     * @param integer $angle 回転角度
     * @return boolean
     */
    public function swirl($angle)
    {        
        $command = 'convert';

        $param  = '-swirl ';
        $param .= $angle.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の上下反転
     *
     * @access public
     * @return boolean
     */
    public function flip()
    {        
        $command = 'convert';

        $param  = '-flip ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の左右反転
     *
     * @access public
     * @return boolean
     */
    public function flop()
    {
        $command = 'convert';

        $param  = '-flop ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の波加工
     *
     * @access public
     * @param integer $height 波の高さ
     * @param integer $width 波の幅
     * @return boolean
     */
    public function wave($height, $width)
    {
        $command = 'convert';

        $param  = '-wave ';
        $param .= $height.'x'.$width.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の装飾模様
     *
     * @access public
     * @param integer $radius 範囲
     * @param integer $x x軸のトリムピクセル
     * @param integer $y y軸のトリムピクセル
     * @param integer $sigma シグマ
     * @return boolean
     */
    public function vignette($radius, $x=0, $y=0, $sigma=10)
    {
        $sigma = empty($sigma)?'1':$sigma;

        $command = 'convert';

        $param  = '-vignette ';
        $param .= $radius.'x'.$sigma.'+'.$x.'+'.$y.'% ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
          effects
      _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/

    /**
     * 対象画像をぼかす
     *
     * @access public
     * @param integer $radius
     * @param integer $sigma
     * @return boolean
     */
    public function blur($radius, $sigma=null)
    {
        $sigma = empty($sigma)?'':'x'.$sigma;
        $command = 'convert';

        $param  = '-blur ';
        $param .= $radius.$sigma.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像に枠線をつける
     *
     * @access public
     * @param string $color
     * @param integer $width
     * @return boolean
     */
    public function border($color, $width=null)
    {
        $width = empty($width)?'5':$width;
        $command = 'convert';

        $param  = '-border ';
        $param .= $width.'x'.$width.' ';
        $param .= '-bordercolor ';
        $param .= $color.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の木炭加工
     *
     * @access public
     * @param integer $factor 要素
     * @return boolean
     */
    public function charcoal($factor)
    {
        $command = 'convert';

        $param  = '-charcoal ';
        $param .= $factor.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のコントラスト調整
     *
     * @access public
     * @param integer $black 黒バランス(%)
     * @param integer $white 白バランス(%)
     * @return boolean
     */
    public function contrast($black, $white=null)
    {
        $white = empty($white)?'':'x'.$white;
        
        $command = 'convert';

        $param  = '-contrast-stretch ';
        $param .= $black.$white.'% ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の斑点を減少
     *
     * @access public
     * @return boolean
     */
    public function despeckle()
    {
        $command = 'convert';

        $param  = '-despeckle ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像にエッジを効かす
     *
     * @access public
     * @param integer $radius 範囲
     * @return boolean
     */
    public function edge($radius)
    {
        $command = 'convert';

        $param  = '-edge ';
        $param .= $radius.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のエンボス加工
     *
     * @access public
     * @param integer $radius 範囲
     * @return boolean
     */
    public function emboss($radius)
    {
        $command = 'convert';

        $param  = '-emboss ';
        $param .= $radius.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のエンハンス加工
     *
     * @access public
     * @return boolean
     */
    public function enhance()
    {
        $command = 'convert';

        $param  = '-enhance ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の均一化
     *
     * @access public
     * @return boolean
     */
    public function equalize()
    {
        $command = 'convert';

        $param  = '-equalize ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のフレーム
     *
     * @access public
     * @param integer $color 色
     * @param integer $width 枠幅
     * @param integer $outer 外側
     * @param integer $inner 内側
     * @return boolean
     */
    public function frame($color, $width=18, $outer=4, $inner=4)
    {
        $command = 'convert';

        $param  = '-frame ';
        $param .= $width.'x'.$width;
        $param .= '+'.$outer.'+'.$inner.' ';
        $param .= '-mattecolor ';
        $param .= $color.' ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のガウス加工
     *
     * @access public
     * @param integer $radius 範囲
     * @param integer $sigma シグマ
     * @return boolean
     */
    public function gaussian($radius, $sigma=null)
    {
        $sigma = empty($sigma)?'':'x'.$sigma;
        
        $command = 'convert';

        $param  = '-gaussian ';
        $param .= $radius.$sigma.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のメディアン加工
     *
     * @access public
     * @param integer $radius 範囲
     * @return boolean
     */
    public function median($radius)
    {
        $command = 'convert';

        $param  = '-median ';
        $param .= $radius.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の明るさ・彩度・色合いの調整
     *
     * @access public
     * @param integer $brightness 明るさ
     * @param integer $saturation 彩度
     * @param boolean $hue 色合い 
     * @return boolean
     */
    public function modulate($brightness, $saturation=null, $hue=null)
    {
        $saturation = empty($saturation)?'':','.$saturation;
        $hue = empty($hue)?'':','.$hue;
        
        $command = 'convert';

        $param  = '-modulate ';
        $param .= $brightness.$saturation.$hue.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のブレ加工
     *
     * @access public
     * @param integer $radius 範囲
     * @param integer $sigma シグマ
     * @param boolean $angle 角度 
     * @return boolean
     */
    public function motionblur($radius, $sigma=null, $angle=null)
    {
        $sigma = empty($sigma)?'':'x'.$sigma;
        $angle = empty($angle)?'':'+'.$angle;
        
        $command = 'convert';

        $param  = '-motion-blur ';
        $param .= $radius.$sigma.$angle.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の色素反転
     *
     * @access public
     * @return boolean
     */
    public function negate()
    {
        $command = 'convert';

        $param  = '-negate ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のノーマライズ
     *
     * @access public
     * @return boolean
     */
    public function normalize()
    {        
        $command = 'convert';

        $param  = '-normalize ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のノイズ加工
     *
     * @access public
     * @param integer $radius 範囲
     * @return boolean
     */
    public function noise($radius)
    {
        $command = 'convert';

        $param  = '-noise ';
        $param .= $radius.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のペイント加工
     *
     * @access public
     * @param integer $radius 範囲
     * @return boolean
     */
    public function paint($radius)
    {
        $command = 'convert';

        $param  = '-paint ';
        $param .= $radius.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の盛り上げ
     *
     * @access public
     * @param integer $width 幅
     * @param integer $height 高さ
     * @return boolean
     */
    public function raise($width, $height=null)
    {
        $height = empty($height)?$width:$height;

        $command = 'convert';

        $param  = '-raise ';
        $param .= $width.'x'.$height.' ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像の陰影加工
     *
     * @access public
     * @param integer $azimuth 照明角度
     * @param integer $elevation 陰影距離
     * @return boolean
     */
    public function shade($azimuth, $elevation)
    {
        $command = 'convert';

        $param  = '-shade ';
        $param .= $azimuth.'x'.$elevation.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のシャープ加工
     *
     * @access public
     * @param integer $radius 範囲
     * @param integer $sigma シグマ
     * @return boolean
     */
    public function sharpen($radius, $sigma=null)
    {
        $sigma = empty($sigma)?'':'x'.$sigma;
        
        $command = 'convert';

        $param  = '-sharpen ';
        $param .= $radius.$sigma.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のソラリゼーション加工
     *
     * @access public
     * @param integer $threshold 敷居値
     * @return boolean
     */
    public function solarize($threshold)
    {
        $command = 'convert';

        $param  = '-solarize ';
        $param .= $threshold.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のスプレッド加工
     *
     * @access public
     * @param integer $amount 広がり幅
     * @return boolean
     */
    public function spread($amount)
    {
        $command = 'convert';

        $param  = '-spread ';
        $param .= $amount.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のスレショルド加工
     *
     * @access public
     * @param integer $value 値
     * @return boolean
     */
    public function threshold($value)
    {
        $command = 'convert';

        $param  = '-threshold ';
        $param .= $value.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 対象画像のアンシャープ加工
     *
     * @access public
     * @param integer $radius 範囲
     * @param integer $sigma シグマ
     * @param integer $amount 広がり幅
     * @param integer $threshold 敷居値
     * @return boolean
     */
    public function unsharp($radius, $sigma=null, $amount=null, $threshold=null)
    {
        $sigma = empty($sigma)?'':'x'.$sigma;
        $amount = empty($amount)?'':'+'.$amount;
        $threshold = empty($threshold)?'':'+'.$threshold;
        
        $command = 'convert';

        $param  = '-unsharp ';
        $param .= $radius.$sigma.$amount.$threshold.' ';
        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
          draw
      _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/*/

    /**
     * 色の設定
     *
     * @access public
     * @param string $fill 筆の色
     * @param string $stroke ペンの色
     * @param string $width  ペンの太さ
     * @return boolean
     */
    public function setColor($fill, $stroke=null, $width=null) 
    {
        $stroke = empty($stroke)?$fill:$stroke;

        $this->_fill_color   = $fill;
        $this->_stroke_color = $stroke;
        $this->_stroke_width = empty($width)?$this->_stroke_width:$width;
    }

    /**
     * フォントの設定
     *
     * @access public
     * @param string $filename ファイル名
     * @param string $pointsize 文字の大きさ
     * @param string $width  ペンの太さ
     * @return boolean
     */
    public function setFont($filename,$pointsize=null, $width=null)
    {
        $this->_font = $filename;
        $this->_pointsize = empty($pointsize)?$this->_pointsize:$pointsize;
        $this->_stroke_width = empty($width)?$this->_stroke_width:$width;
    }

    /**
     * 文字の書き出し
     *
     * @access public
     * @param string $string 文字列
     * @param integer $x   x軸
     * @param integer $y   y軸
     * @param integer $xrotate   x軸の回転
     * @param integer $yrotate   y軸の回転
     * @return boolean
     */
    public function annotate($string, $x=0, $y=0, $xrotate=0, $yrotate=0) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';
        $param .= '-pointsize ';
        $param .= $this->_pointsize.' ';

        $param .= '-annotate ';
        $param .= $xrotate.'x'.$yrotate;
        $param .= '+'.$x.'+'.$y.' ';
        $param .= '"'.$string.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 文字列の描画
     *
     * @access public
     * @param integer $x   x軸
     * @param integer $y   y軸
     * @param string $string 文字列
     * @param string $pointsize 文字の大きさ
     * @return boolean
     */
    public function text($x, $y, $string, $pointsize=10, $gravity=null) 
    {
        $this->_pointsize = $pointsize;

        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-font ';
        $param .= '"'.$this->_font.'" ';
        $param .= '-pointsize ';
        $param .= $this->_pointsize.' ';
        if (!empty($gravity)){
            $param .= '-gravity '.$gravity.' ';
        }

        $param .= '-draw "text ';
        $param .= $x.','.$y.' ';
        $param .= "'".$string."'".'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 点の描画
     *
     * @access public
     * @param integer $x x軸
     * @param integer $y y軸
     * @return boolean
     */
    public function point($x, $y) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "point ';
        $param .= $x.','.$y.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 線の描画
     *
     * @access public
     * @param integer $left   左上のx軸
     * @param integer $top    左上のy軸
     * @param integer $right  右下のx軸
     * @param integer $bottom 右下のy軸
     * @return boolean
     */
    public function line($left, $top, $right, $bottom) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "line ';
        $param .= $left.','.$top.' '.$right.','.$bottom.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 四角の描画
     *
     * @access public
     * @param integer $left   左上のx軸
     * @param integer $top    左上のy軸
     * @param integer $right  右下のx軸
     * @param integer $bottom 右下のy軸
     * @return boolean
     */
    public function rectangle($left, $top, $right, $bottom) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "rectangle ';
        $param .= $left.','.$top.' '.$right.','.$bottom.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 角丸四角の描画
     *
     * @access public
     * @param integer $left   左上のx軸
     * @param integer $top    左上のy軸
     * @param integer $right  右下のx軸
     * @param integer $bottom 右下のy軸
     * @param integer $width  幅
     * @param integer $height 高さ
     * @return boolean
     */
    public function roundrectangle($left, $top, $right, $bottom, $width, $height)
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "roundrectangle ';
        $param .= $left.','.$top.' '.$right.','.$bottom.' ';
        $param .= $width.','.$height.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 円の描画
     *
     * @access public
     * @param integer $x0  中心のx軸
     * @param integer $y0  中心のy軸
     * @param integer $x1  x軸の大きさ
     * @param integer $y1  y軸の大きさ
     * @return boolean
     */
    public function circle($x0, $y0, $x1, $y1) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "circle ';
        $param .= $x0.','.$y0.' '.$x1.','.$y1.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 楕円の描画
     *
     * @access public
     * @param integer $x   x軸
     * @param integer $y   y軸
     * @param integer $rx  x軸の半径
     * @param integer $ry  y軸の半径
     * @param integer $start_angle 開始角度
     * @param integer $end_angle   終了角度
     * @return boolean
     */
    public function ellipse($x, $y, $rx, $ry, $start_angle=0, $end_angle=360) 
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "ellipse ';
        $param .= $x.','.$y.' '.$rx.','.$ry.' ';
        $param .= $start_angle.','.$end_angle.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 円弧の描画
     *
     * @access public
     * @param integer $left   左上のx軸
     * @param integer $top    左上のy軸
     * @param integer $right  右下のx軸
     * @param integer $bottom 右下のy軸
     * @param integer $start_angle 開始角度
     * @param integer $end_angle   終了角度
     * @return boolean
     */
    public function arc($left, $top, $right, $bottom, $start_angle=0, $end_angle=180)
    {
        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "arc ';
        $param .= $left.','.$top.' '.$right.','.$bottom.' ';
        $param .= $start_angle.','.$end_angle.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 多線の描画
     *
     * @access public
     * @param array $points x,yポイント配列
     *      $points = array(x0, y0, x1, y1 ...)
     * @return boolean
     */
    public function polyline($points) 
    {
        $separator = array(',',' ');
        $point = '';
        foreach ($points as $row=>$value){
            $point .= $value.$separator[(1 & $row)];
        }

        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "polyline ';
        $param .= $point.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * 多角形の描画
     *
     * @access public
     * @param array $points x,yポイント配列
     *      $points = array(x0, y0, x1, y1 ...)
     * @return boolean
     */
    public function polygon($points) 
    {
        $separator = array(',',' ');
        $point = '';
        foreach ($points as $row=>$value){
            $point .= $value.$separator[(1 & $row)];
        }

        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "polygon ';
        $param .= $point.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }

    /**
     * ペジェ曲線の描画
     *
     * @access public
     * @param array $points x,yポイント配列
     *      $points = array(x0, y0, x1, y1 ...)
     * @return boolean
     */
    public function bezier($points) 
    {
        $separator = array(',',' ');
        $point = '';
        foreach ($points as $row=>$value){
            $point .= $value.$separator[(1 & $row)];
        }

        $command = 'convert';

        $param  = '-fill ';
        $param .= $this->_fill_color.' ';
        $param .= '-stroke ';
        $param .= $this->_stroke_color.' ';
        $param .= '-strokewidth ';
        $param .= $this->_stroke_width.' ';

        $param .= '-draw "bezier ';
        $param .= $point.'" ';

        $param .= $this->_format.':- '.$this->_format.':-';
        
        return $this->command($command, $param);
    }
} // class Image_ImageMagick
?>