Animiertes Gif aus Einzelbildern erstellen

Hallo zusammen,

habe gelesen, dass ihr aus mehreren Bildern der Überwachungskamera ein animiertes Gif erstellt.
Würde diese Funktion auch gerne mit Telegram nutzen.

Hat hier jemand zufällig einen Codeschnipsel, wie man ein Gif erstellen kann?

Vielen Dank!

Grüße
Dan

Ich benutze die Bibliothek, welche auch Raketenschnecke für sein Rainforecast verwendet. Ich such es nacher mal raus.

Gesendet von meinem SM-G900F mit Tapatalk

Super, vielen Dank!

Schöne Grüße
Dan

Hi Dan,

die GifCreator Klasse findes Du hier GitHub - Sybio/GifCreator: GifCreator is a PHP class that creates animated GIF from multiple images
Sag Bescheid, falls Du Hilfe brauchst, lässt sich aber ganz einfach einbinden.

Hi normi,

vielen Dank für den Link.
Mal ne blöde Frage, muss ich die Dateien irgendwo bestimmtes hin speichern zum einbinden?

Vielen Dank!

Grüße
Dan

Nein, nur im Array angeben wo sie liegen.

Gesendet von meinem SM-G900F mit Tapatalk

Hi normi,

danke für die Antwort. Das habe ich verstanden. Ich frage mich nur, wie ich die externe Klasse einbinde? Geht das auch mit include und dann Verweis auf die GifCreator.php Datei?
Bis jetzt bekomme ich leider immer eine Fehlermeldung!

Danke!

Ich habe mir die php-Datei des GifCreater in das IPS-Script Verzeichnis kopiert. Den 1. Eintrag namespace GifCreator habe ich gelöscht.
Und das ist mein Script um aus mehreren Einzelbildern von Blueiris ein Gif zu erzeugen. Vielleicht hilft es Dir ja.

include("C:/IP-Symcon/scripts/GifCreator.php");

//egal wie viele die Bilder müssen nur dem Schema CamX_000.jpg folgen    
$cam              = "Cam9";    
$dir                 = "C:/BlueIris/www/";    
$alleD             = scandir($dir);
    foreach($alleD as $datei)    
     { 
        $dateiinfo = pathinfo($dir."/".$datei);
         if ($dateiinfo['extension'] == "jpg")
           { 
               if (strpos($datei, $cam."_") === 0) 
                  {               
                           $filelist[] = $dir.$datei; 
                           $Intervalle[]  = 50; 
                   }    
             }   
        }
    //    print_r($filelist);
    // Nun sind alle benötigten Dateinamen im Array und ich kann das GIF erzeugen    
     $GIF                     = new GifCreator();
     $GIF->create($filelist, $Intervalle, 0);
    // GIF auf Massenspeicher ablegen   
     $GIF_path             = $dir.$cam.".gif";
     $GIF_Binary         = $GIF->getGif();
     file_put_contents($GIF_path, $GIF_Binary);

Hallo Norman,

vielen Dank, leider geht das bei mir wieso auch immer nicht…

Folgend mein Skript:

<?

include(IPS_GetScriptFile(56181 /*[Skripte\Funktionen\functionListFiles]*/));

include("C:/IP-Symcon/scripts/GifCreator.php");

$verzeichnis = "C:/IP-Symcon/Cams/1/History";

$bilddaten = list_files($verzeichnis);

$anzahl = count($bilddaten);

$Path_To_GifFile = IPS_GetKernelDir()."\\cams\\1\\History\	est.gif";


// Create an array containing file paths, resource var (initialized with imagecreatefromXXX),
// image URLs or even binary code from image files.
// All sorted in order to appear.
$frames = array(

//	 imagecreatefromjpg("/../images/pic1.png"), // Resource var
//    "/../images/pic2.png", // Image file path
//    file_get_contents("/../images/pic3.jpg"), // Binary source code
//    'http://thisisafakedomain.com/images/pic4.jpg', // URL

IPS_GetKernelDir()."\\cams\\1\\History\\".$bilddaten[$anzahl-1],
IPS_GetKernelDir()."\\cams\\1\\History\\".$bilddaten[$anzahl-2],

);

// Create an array containing the duration (in millisecond) of each frames (in order too)
$durations = array(40, 80, 40, 20);

// Initialize and create the GIF !
$gc = new GifCreator();
$gc->create($frames, $durations, 5);


file_put_contents($Path_To_GifFile, $gifBinary);



?>

Dann bekomm ich folgende Fehlermeldung:

Irgendjemand ne Idee?

Danke!

Poste mal den Quelltext von der GifCreator.php.
Komisch ist auch, dass er an Zeile 49 rum meckert, obwohl nur 43 da sind.:confused:

<?php

namespace GifCreator;

/**
 * Create an animated GIF from multiple images
 * 
 * @version 1.0
 * @link https://github.com/Sybio/GifCreator
 * @author Sybio (Clément Guillemain  / @Sybio01)
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @copyright Clément Guillemain
 */
class GifCreator
{
    /**
     * @var string The gif string source (old: this->GIF)
     */
    private $gif;
    
    /**
     * @var string Encoder version (old: this->VER)
     */
	private $version;
    
    /**
     * @var boolean Check the image is build or not (old: this->IMG)
     */
    private $imgBuilt;

    /**
     * @var array Frames string sources (old: this->BUF)
     */
	private $frameSources;
    
    /**
     * @var integer Gif loop (old: this->LOP)
     */
	private $loop;
    
    /**
     * @var integer Gif dis (old: this->DIS)
     */
	private $dis;
    
    /**
     * @var integer Gif color (old: this->COL)
     */
	private $colour;
    
    /**
     * @var array (old: this->ERR)
     */
	private $errors;
 
    // Methods
    // ===================================================================================
    
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->reset();
        
        // Static data
        $this->version = 'GifCreator: Under development';
        $this->errors = array(
            'ERR00' => 'Does not supported function for only one image.',
    		'ERR01' => 'Source is not a GIF image.',
    		'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.',
    		'ERR03' => 'Does not make animation from animated GIF source.',
        );
    }

	/**
     * Create the GIF string (old: GIFEncoder)
     * 
     * @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs
     * @param array $durations An array containing the duration of each frame
     * @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop)
     * 
     * @return string The GIF string source
     */
	public function create($frames = array(), $durations = array(), $loop = 0)
    {
		if (!is_array($frames) && !is_array($GIF_tim)) {
            
            throw new \Exception($this->version.': '.$this->errors['ERR00']);
		}
        
		$this->loop = ($loop > -1) ? $loop : 0;
		$this->dis = 2;
        
		for ($i = 0; $i < count($frames); $i++) {
		  
			if (is_resource($frames[$i])) { // Resource var
                
                $resourceImg = $frames[$i];
                
                ob_start();
                imagegif($frames[$i]);
                $this->frameSources[] = ob_get_contents();
                ob_end_clean();
                
            } elseif (is_string($frames[$i])) { // File path or URL or Binary source code
			     
                if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path
                    
                    $frames[$i] = file_get_contents($frames[$i]);                    
                }
                
                $resourceImg = imagecreatefromstring($frames[$i]);
                
                ob_start();
                imagegif($resourceImg);
                $this->frameSources[] = ob_get_contents();
                ob_end_clean();
                 
			} else { // Fail
                
                throw new \Exception($this->version.': '.$this->errors['ERR02'].' ('.$mode.')');
			}
            
            if ($i == 0) {
                
                $colour = imagecolortransparent($resourceImg);
            }
            
			if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr($this->frameSources[$i], 0, 6) != 'GIF89a') {
			 
                throw new \Exception($this->version.': '.$i.' '.$this->errors['ERR01']);
			}
            
			for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))), $k = TRUE; $k; $j++) {
			 
				switch ($this->frameSources[$i] { $j }) {
				    
					case '!':
                    
						if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') {
                            
                            throw new \Exception($this->version.': '.$this->errors['ERR03'].' ('.($i + 1).' source).');
						}
                        
					break;
                        
					case ';':
                    
						$k = false;
					break;
				}
			}
            
            unset($resourceImg);
		}
		
        if (isset($colour)) {
            
            $this->colour = $colour;
                                    
        } else {
            
            $red = $green = $blue = 0;
            $this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1;
        }
        
		$this->gifAddHeader();
        
		for ($i = 0; $i < count($this->frameSources); $i++) {
		  
			$this->addGifFrames($i, $durations[$i]);
		}
        
		$this->gifAddFooter();
        
        return $this->gif;
	}
    
    // Internals
    // ===================================================================================
    
	/**
     * Add the header gif string in its source (old: GIFAddHeader)
     */
	public function gifAddHeader()
    {
		$cmap = 0;

		if (ord($this->frameSources[0] { 10 }) & 0x80) {
		  
			$cmap = 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07));

			$this->gif .= substr($this->frameSources[0], 6, 7);
			$this->gif .= substr($this->frameSources[0], 13, $cmap);
			$this->gif .= "!\377\13NETSCAPE2.0\3\1".$this->encodeAsciiToChar($this->loop)."\0";
		}
	}
    
	/**
     * Add the frame sources to the GIF string (old: GIFAddFrames)
     * 
     * @param integer $i
     * @param integer $d
     */
	public function addGifFrames($i, $d)
    {
		$Locals_str = 13 + 3 * (2 << (ord($this->frameSources[ $i ] { 10 }) & 0x07));

		$Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1;
		$Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end);

		$Global_len = 2 << (ord($this->frameSources[0 ] { 10 }) & 0x07);
		$Locals_len = 2 << (ord($this->frameSources[$i] { 10 }) & 0x07);

		$Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07)));
		$Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07)));

		$Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 0).chr(($d >> 0 ) & 0xFF).chr(($d >> 8) & 0xFF)."\x0\x0";

		if ($this->colour > -1 && ord($this->frameSources[$i] { 10 }) & 0x80) {
		  
			for ($j = 0; $j < (2 << (ord($this->frameSources[$i] { 10 } ) & 0x07)); $j++) {
			 
				if (ord($Locals_rgb { 3 * $j + 0 }) == (($this->colour >> 16) & 0xFF) &&
					ord($Locals_rgb { 3 * $j + 1 }) == (($this->colour >> 8) & 0xFF) &&
					ord($Locals_rgb { 3 * $j + 2 }) == (($this->colour >> 0) & 0xFF)
				) {
					$Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 1).chr(($d >> 0) & 0xFF).chr(($d >> 8) & 0xFF).chr($j)."\x0";
					break;
				}
			}
		}
        
		switch ($Locals_tmp { 0 }) {
		  
			case '!':
            
				$Locals_img = substr($Locals_tmp, 8, 10);
				$Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);
                                
			break;
                
			case ',':
            
				$Locals_img = substr($Locals_tmp, 0, 10);
				$Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);
                                
			break;
		}
        
		if (ord($this->frameSources[$i] { 10 }) & 0x80 && $this->imgBuilt) {
		  
			if ($Global_len == $Locals_len) {
			 
				if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) {
				    
					$this->gif .= $Locals_ext.$Locals_img.$Locals_tmp;
                    
				} else {
				    
					$byte = ord($Locals_img { 9 });
					$byte |= 0x80;
					$byte &= 0xF8;
					$byte |= (ord($this->frameSources[0] { 10 }) & 0x07);
					$Locals_img { 9 } = chr($byte);
					$this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
				}
                
			} else {
			 
				$byte = ord($Locals_img { 9 });
				$byte |= 0x80;
				$byte &= 0xF8;
				$byte |= (ord($this->frameSources[$i] { 10 }) & 0x07);
				$Locals_img { 9 } = chr($byte);
				$this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
			}
            
		} else {
		  
			$this->gif .= $Locals_ext.$Locals_img.$Locals_tmp;
		}
        
		$this->imgBuilt = true;
	}
    
	/**
     * Add the gif string footer char (old: GIFAddFooter)
     */
	public function gifAddFooter()
    {
		$this->gif .= ';';
	}
    
	/**
     * Compare two block and return the version (old: GIFBlockCompare)
     * 
     * @param string $globalBlock
     * @param string $localBlock
     * @param integer $length
     * 
     * @return integer
	 */
	public function gifBlockCompare($globalBlock, $localBlock, $length)
    {
		for ($i = 0; $i < $length; $i++) {
		  
			if ($globalBlock { 3 * $i + 0 } != $localBlock { 3 * $i + 0 } ||
				$globalBlock { 3 * $i + 1 } != $localBlock { 3 * $i + 1 } ||
				$globalBlock { 3 * $i + 2 } != $localBlock { 3 * $i + 2 }) {
				
                return 0;
			}
		}

		return 1;
	}
    
	/**
     * Encode an ASCII char into a string char (old: GIFWord)
     * 
     * $param integer $char ASCII char
     * 
     * @return string
	 */
	public function encodeAsciiToChar($char)
    {
		return (chr($char & 0xFF).chr(($char >> 8) & 0xFF));
	}
    
    /**
     * Reset and clean the current object
     */
    public function reset()
    {
        $this->frameSources;
        $this->gif = 'GIF89a'; // the GIF header
        $this->imgBuilt = false;
        $this->loop = 0;
        $this->dis = 2;
        $this->colour = -1;
    }
    
    // Getter / Setter
    // ===================================================================================
    
	/**
     * Get the final GIF image string (old: GetAnimation)
     * 
     * @return string
	 */
	public function getGif()
    {
		return $this->gif;
	}
}

Das mit dem Fehler ist schon okay, hatte nachträglich noch ein paar Zeilen entfernt. Das Problem liegt in Zeile 35:

// Initialize and create the GIF !
$gc = new GifCreator();

Danke!

nimm mal oben die Zeile raus

namespace GifCreator; 

Danke, das war die Lösung…

Schöne Grüße
Dan

Hallo Zusammen,
Bastel grade mit dem GifCreator rum. Im ersten Schritt lief das Script auch. Ich habe aber an mehreren Stellen das BildAchiv Modul laufen. Hier habe ich gelernte um die Schreibzugriffe auf ssd speicher so gering wie möglich zu halten befinden sich für Bilder im cache.
Wie man die Bilder dann Speichert und dann abruft ist auch klar. Hat es denn schon jemand so umgebaut das man die Bilder erst gar nicht zwischen Speicher werden müssen und direkt aus dem cache in ein Gif erstellt und wenn dann auch nur in den Cache speichert ?
Aktuell sieht mein Scrit so aus:

<?

include("C:/IP-Symcon/scripts/GifCreator.php");

$Archiv_ID = 11798 /*[Skripte\Skripte\Wetterstation\Unwetterzentrale NRW (Radarbild)\BildArchiv\Bilderarchiv]*/;

foreach(IPS_GetChildrenIDs($Archiv_ID) as $Media)    
     { 
	 	$ido_info = IPS_GetObject($Media);
		$ido = $ido_info['ObjectID'];
		$ido_name = IPS_GetName($ido);
		$ido_typ = $ido_info['ObjectType'];
		 If ($ido_typ == 5){
		  $idm_info = IPS_GetMedia ($ido );
		  $idm_file = $idm_info['MediaFile'];
		  
		  	//$filelist[] = "c:/IP-Symcon/".$idm_file;
			 $filelist[] = $ido;
			// $bild = base64_decode(IPS_GetMediaContent($ido)); 
            $Intervalle[]  = 50; 
		 echo "$ido_name - $idm_file 
";
		 }

	 }
print_r ($filelist);

    // Nun sind alle benötigten Dateinamen im Array und ich kann das GIF erzeugen    
     $GIF                = new GifCreator();
     $GIF->create($filelist, $Intervalle, 0);
    // GIF auf Massenspeicher ablegen   
     $GIF_path           = "C:/IPS-Eigene_Dateien/gif-bilder/wetter.gif";
     $GIF_Binary         = $GIF->getGif();
     file_put_contents($GIF_path, $GIF_Binary); 

Bekomme aber immer die Fehlermedung .
Undefined variable: mode in C:\IP-Symcon\scripts\GifCreator.php on line 122
Vieleicht weiß ja jemand weiter oder hat ein Beispiel Script.

Gruß Stephan