<?php

    /**
     * This is a pure php emulation of the PHP module FFmpeg-PHP.
     * There is one extra function here. ffmpeg_animated_gif::saveNow();
     * @author Oliver Lillie (aka buggedcom) <publicmail@buggedcom.co.uk>
     * @package PHPVideoToolkit
     * @license BSD
     * @copyright Copyright (c) 2008 Oliver Lillie <http://www.buggedcom.co.uk>
     * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
     * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
     * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
     * is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be
     * included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
     * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     * @uses GifEncoder 
     *      - @link http://www.phpclasses.org/browse/package/3163.html
     *      - @link http://phpclasses.gifs.hu/show.php?src=GIFEncoder.class.php
     *      - @author László Zsidi
     *      - @license Freeware.
     * @see ffmpeg-php, 
     *      - @link http://ffmpeg-php.sourceforge.net/
     *      - @author Todd Kirby.
     *      - all phpdoc documentation is lifted directly from the ffmpeg-php docs
     */
    
    if(!defined('DS'))
    {
        define('DS', DIRECTORY_SEPARATOR);
    }
    
    class ffmpeg_animated_gif
    {
        
        private $_frames            = array();
        private $_width             = null;
        private $_height            = null;
        private $_frame_rate        = null;
        private $_loop_count        = null;
        private $_output_file_path  = null;
        private $_toolkit_class     = null;
        private $_unlink_files      = array();
        private $_saved             = false;
        
        /**
         * Class Constructor
         * Create a new ffmpeg_animated_gif object.
         * @param resource $output_file_path Location in the filesystem where the animated gif will be written.
         * @param resource $width Width of the animated gif.
         * @param resource $height Height of the animated gif.
         * @param resource $frame_rate Frame rate of the animated gif in frames per second.
         * @param resource $loop_count Number of times to loop the animation. Put a zero here to loop forever or omit this parameter to disable looping.
         */
        function __construct($output_file_path, $width, $height, $frame_rate, $loop_count=false)
        {
            $this->_output_file_path    = $output_file_path;
            $this->_width               = $width;
            $this->_height              = $height;
            $this->_frame_rate          = $frame_rate;
            $this->_loop_count          = $loop_count;
        }
        
        /**
         * Class Destructor
         * saves the file
         */
        function __destruct()
        {
//          save the output
            $this->saveNow();
//          destroy all image resources
            if(count($this->_frames))
            {
                foreach($this->_frames as $key=>$frame)
                {
                    imagedestroy($frame->toGDImage());
                }
            }
//          loop through the temp files to remove 
            if(!empty($this->_unlink_files))
            {
                foreach ($this->_unlink_files as $key=>$file)
                {
                    @unlink($file);
                }
                $this->_unlink_files = array();
            }
        }
        
        /**
         * This function IS NOT PROVIDED IN FFMPEG-PHP as it creates the gif as frames are added. to save memory in
         * php and practicality purposes this isn't really possible. It will overwrite any file.
         * @access public
         * @uses GifEncoder
         *      - @link http://www.phpclasses.org/browse/package/3163.html
         *      - @link http://phpclasses.gifs.hu/show.php?src=GIFEncoder.class.php
         *      - @author László Zsidi
         *      - @license Freeware.
         * @param string $tmp_directory The temp directory to work with. (remember the trailing slash)
         * @return boolean
         */
        public function saveNow($tmp_directory='/tmp/')
        {
            if($this->_saved === false)
            {
                $this->_saved = true;
//              check there are frames to make a gif
                if(!count($this->_frames))
                {
                    return false;
                }
                if(!class_exists('GIFEncoder'))
                {
                    require_once dirname(__FILE__).DS.'gifencoder'.DS.'GIFEncoder.class.phpvideotoolkit.php';
                }
//              save all the images from the ffmpeg_frames
                $files = array();
                $delays = array();
                $delay = (1/$this->_frame_rate)*100;
                foreach($this->_frames as $key=>$frame)
                {
                    $file = $tmp_directory.'fag-'.uniqid(time().'-').'.gif';
                    if(!imagegif($frame->toGDImage(), $file))
                    {
                        return false;
                    }
//                  add file to array so it out deletes on close
                    array_push($this->_unlink_files, $file);
                    array_push($files, $file);
                    array_push($delays, $delay);
                }
//              convert the images
                $gif = new GIFEncoder($files, $delays, $this->_loop_count, 2, 0, 0, 0, 0, 'url');
                $gif_data = $gif->GetAnimation();
                if(!$gif_data)
                {
                    return false;
                }
//              write the gif
                if (!$handle = fopen($this->_output_file_path, 'w'))
                {
                    return false;
                }
                if (fwrite($handle, $gif_data) === false)
                {
                    return false;
                }
                fclose($handle);
                return true;
            }
            return false;
        }
        
        /**
         * Add a frame to the end of the animated gif.
         * @access public
         * @param resource $output_file_path The ffmpeg_frame object to add to the end of the animated gif.
         * @param boolean $save If true the gif will save after the frame has been added. 
         *      NOTE: this param does not feature in the actuall ffmpeg-php module.
         * @return boolean
         */
        public function addFrame($frame_to_add, $save=false)
        {
            if(get_class($frame_to_add) == 'ffmpeg_frame' && $frame_to_add->hasValidResource())
            {
                array_push($this->_frames, $frame_to_add);
                $this->_saved = false;
                return $save === true ? $this->saveNow() : true;
            }
            return false;
        }
        
    }
