GD Animated Gifs

Status
Not open for further replies.

helraizer

Baseband Member
Messages
26
Hey folks,

I'm working on animating gifs in GD. I've adapted the use of the GIFEncoder class from phpclasses.
original
gif.php

PHP:
<?php
 
 
Class GIFAnimator {
    var $GIF = "GIF89a";       
    var $VER = "GIFEncoder V2.05";    
 
    var $BUF = Array ( );
    var $LOP =  0;
    var $DIS =  2;
    var $COL = -1;
    var $IMG = -1;
 
    var $ERR = Array (
        ERR00=>"Does not supported function for only one image!",
        ERR01=>"Source is not a GIF image!",
        ERR02=>"Unintelligible flag ",
        ERR03=>"Does not make animation from animated GIF source",
    );
 
   
    function GIFAnimator    (
                            $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis,
                            $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod
                        ) {
        if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_tim ) ) {
            printf    ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] );
            exit    ( 0 );
        }
        $this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0;
        $this->DIS = ( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2;
        $this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ?
                        ( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1;
 
        for ( $i = 0; $i < count ( $GIF_src ); $i++ ) {
            if ( strToLower ( $GIF_mod ) == "url" ) {
                $this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) );
            }
            else if ( strToLower ( $GIF_mod ) == "bin" ) {
                $this->BUF [ ] = $GIF_src [ $i ];
            }
            else {
                printf    ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod );
                exit    ( 0 );
            }
            if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) {
                printf    ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] );
                exit    ( 0 );
            }
            for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) {
                switch ( $this->BUF [ $i ] { $j } ) {
                    case "!":
                        if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) {
                            printf    ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) );
                            exit    ( 0 );
                        }
                        break;
                    case ";":
                        $k = FALSE;
                        break;
                }
            }
        }
        GIFAnimator::GIFHead ( );
        for ( $i = 0; $i < count ( $this->BUF ); $i++ ) {
            GIFAnimator::GIFGetFrames ( $i, $GIF_dly [ $i ] );
        }
        GIFAnimator::GIFFoot ( );
    }
   
    function GIFHead ( ) {
        $cmap = 0;
 
        if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) {
            $cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) );
 
            $this->GIF .= substr ( $this->BUF [ 0 ], 6, 7        );
            $this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap    );
            $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFAnimator::GIFWord ( $this->LOP ) . "\0";
        }
    }
  
    function GIFGetFrames ( $i, $d ) {
 
        $Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) );
 
        $Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1;
        $Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end );
 
        $Global_len = 2 << ( ord ( $this->BUF [ 0  ] { 10 } ) & 0x07 );
        $Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 );
 
        $Global_rgb = substr ( $this->BUF [ 0  ], 13,
                            3 * ( 2 << ( ord ( $this->BUF [ 0  ] { 10 } ) & 0x07 ) ) );
        $Locals_rgb = substr ( $this->BUF [ $i ], 13,
                            3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) );
 
        $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS << 2 ) + 0 ) .
                        chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0";
 
        if ( $this->COL > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) {
            for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) {
                if    (
                        ord ( $Locals_rgb { 3 * $j + 0 } ) == ( ( $this->COL >> 16 ) & 0xFF ) &&
                        ord ( $Locals_rgb { 3 * $j + 1 } ) == ( ( $this->COL >>  8 ) & 0xFF ) &&
                        ord ( $Locals_rgb { 3 * $j + 2 } ) == ( ( $this->COL >>  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->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) {
            if ( $Global_len == $Locals_len ) {
                if ( GIFAnimator::GIFBlock ( $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->BUF [ 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->BUF [ $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->IMG  = 1;
    }
    
    function GIFFoot ( ) {
        $this->GIF .= ";";
    }
   
    function GIFBlock ( $GlobalBlock, $LocalBlock, $Len ) {
 
        for ( $i = 0; $i < $Len; $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 );
    }
   
    function GIFWord ( $int ) {
 
        return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) );
    }
    
    function GetAnimation ( ) {
        return ( $this->GIF );
    }
} 
 
?>



I have used

PHP:
<?php
 
include('gif.php');
 
$image = imagecreatefrompng("../mychatbox/user/helraizer1.png");
 
 
if ( $dh = opendir ( "frames/" ) ) {
 
    while ( false !== ( $dat = readdir ( $dh ) ) ) {
 
        if ( $dat != "." && $dat != ".." ) {
 
            $frames [ ] .= "frames/$dat";
 
            $framed [ ] = 20;
 
        }
 
    }
 
    closedir ( $dh );
 
}
   
    foreach( $frames as $thePfhrame )
   
      {
   
          $imgPfhrame = imagecreatefromgif($thePfhrame);
   
          imagecopymerge($image, $imgPfhrame, imageSX($image)/2, imageSY($image)/1.5, 0, 0, 15, 15, 100);
   
          
          
        
      }
      
 
  $gif = new GIFAnimator    (
 
                            $frames, //sources - URL or path
 
                            $framed, //delay times - int
 
                            0, //Animation loops - int - 0 is infinite
 
                            2, //Disposal - int
 
                            -1, -1, -1, //transparency red, green, blue - int
 
                            "url" // source type
 
        );
   
   
    
 
       
 
        header("Content-Type: image/gif");
 
echo $gif->GetAnimation();
 
 
FWrite ( FOpen ( "img.gif", "wb" ), $gif->GetAnimation ( ) );
 
 
?>

and it produces this:

img.gif


As you can see the one that is in middle is animated! So that works perfectly fine, on its own.

However when I put the code in my showimage script (to produce the shoutbox), which is in a different folder, but still has a 'frames' folder with the same frames in it, it gives me the error.

GIFEncoder V2.05: Does not supported function for only one image!

Even though there are 9 frames in the folder.

PHP:
if(stristr($line, ":roll:")) {
            session_register("roll");
            $_SESSION['roll'] = 1;
        }
       
if (isset($filter)) {
header("Content-Type: image/png"); // tell the browser what we're gonna give it
    imagepng($image);
 
} elseif ($page == 1) {
 
if(!isset($_SESSION['roll'])) {
    header("Content-Type: image/png"); // tell the browser what we're gonna give it
    imagepng($image);
 imagepng($image, "./user/" . $user . $box. ".png");
 
} else {
    
     $pos = strpos($line, ":roll:");
 
        if ($font == "palab") {
            $post = $pos * 5.7;
        } elseif ($font == "comicsans") {
            $post = $pos * 6.725;
        } elseif ($font == "calibri") {
            $post = $pos * 5;
        } elseif ($font == "courbd") {
            $post = ($pos * 5.<!-- s8) --><img src=\"{SMILIES_PATH}/icon_cool.gif\" alt=\"8)\" title=\"Cool\" /><!-- s8) --> + 1;
        } elseif ($font == "arial") {
            $post = ($pos * 7.3) + 1;
        } else {
 
        }
    
 
            
      if ( $dh = opendir ( "frames/" ) ) {
 
    while ( false !== ( $dat = readdir ( $dh ) ) ) {
 
        if ( $dat != "." && $dat != ".." ) {
 
            $frames [ ] .= "frames/$dat";
 
            $framed [ ] = 17;
 
        }
 
    }
 
    closedir ( $dh );
 
}
   
    foreach( $frames as $thePfhrame )
   
      {
   
          $imgPfhrame = imagecreatefromgif($thePfhrame);
   
          imagecopymerge($image, $imgPfhrame, ($cur_line_x + $post) + 6, (($cur_line_y + $lineheight) - 30.5), 0, 0, 15, 15, 100);
   
          
          
        
      }
      
 
  $gif = new GIFAnimator    (
 
                            $frames, //sources - URL or path
 
                            $framed, //delay times - int
 
                            0, //Animation loops - int - 0 is infinite
 
                            2, //Disposal - int
 
                            -1, -1, -1, //transparency red, green, blue - int
 
                            "url" // source type
 
        );
   
   
    
 
       
 
        header("Content-Type: image/gif");
 
echo $gif->GetAnimation();
 
 
FWrite ( FOpen ( "helraizer2.gif", "wb" ), $gif->GetAnimation ( ) );
 
}
 
 
else {
    header("Content-Type: image/png"); // tell the browser what we're gonna give it
    imagepng($image);
 
}

The error comes about if $frames isn't an array but, it is. Any idea why this happens?

Sam
 
I'm no good with GD. I'll look it over and see if I can spot a problem, but I suspect you've already done that to the point in which you are bald. :p
 
Status
Not open for further replies.
Back
Top Bottom