<?php

/*
    Copyright SuperRembo (c) 2006

    Version 0.1.2, 01/07/2006

    Use it in any way you like as long as you leave my copyright notice intact.
*/

class GifImage {

    var 
$header;
    var 
$blocks = array();

    function 
GifImage() {
    }

    
/*
    Disposal Method:
        0    No disposal specified.
        1    Do not dispose.
        2    Restore to background color.
        3    Restore to previous.
    */
    
function addControlBlock($delayTime$transparentColorIndex=false$disposalMethod=0) {
        
$transparentColor $transparentColorIndex===false 1;// 1 bit
        
$flags $disposalMethod << 2
            
$transparentColor;
        
$block pack('CCCCSCC'0x210xf94$flags$delayTime$transparentColorIndex0);
        
$this->blocks[] = $block;
    }

    function 
addCommentBlock($comment) {
        
$block pack('CC'0x210xfe);
        
$n strLen($comment);
        for (
$i 0$i $n$i += 255) {
            
$part subStr($comment$i255);
            
$block .= pack('C'strLen($part)) . $part;
        }
        
$block .= pack('C'0x00);
        
$this->blocks[] = $block;
    }

    function 
addImageBlock(&$img) {
        
$gif $this->_getGifData($img);
        list(
$header$block) = $this->_getGifParts($gif);
        
$this->header $header;
        
$this->blocks[] = $block;
    }

    function 
addApplicationBlock($appId$appCode$data) {
        
$block pack('CCC'0x210xff11);
        
$block .= subStr(str_pad($appId8' '), 08);
        
$block .= subStr(str_pad($appCode3' '), 03);

        
$n strLen($data);
        if (
$n==0) return;
        for (
$i 0$i $n$i += 255) {
            
$part subStr($data$i255);
            
$block .= pack('C'strLen($part)) . $part;
        }
        
$block .= pack('C'0x00);

        
$this->blocks[] = $block;
    }

    function 
addLoopBlock($loop=0) {
        
$this->addApplicationBlock('NETSCAPE''2.0'pack('CS'1$loop));
    }

    function 
getImageData() {
        
$data 'GIF89a' $this->header implode(''$this->blocks) . pack('C'0x3b);
        return 
$data;
    }

    function 
streamImage() {
        
header('Content-type: image/gif');
        echo 
$this->getImageData();
    }

    function 
writeImage($filename) {
        
$data $this->getImageData();
        
$h fOpen($filename'wb');
        
fWrite($h$data);
        
fClose($h);
    }

    function 
_getGifData(&$img) {
        
ob_start();
        
imageGif($img);
        
$gif ob_get_contents();
        
ob_end_clean();
        return 
$gif;
    }

    function 
_getGifParts($gif) {
        
// Asume following format
        // Header, 6 bytes
        // Logical Screen Descriptor, 7 bytes
        // Global Color Table, 3*NumberOfColors bytes
        // Image Descriptor, 10 bytes
        // Table Based Image Data, until trailer
        // Trailer, 1 byte

        // Logical Screen Descriptor + Global Color Table
        
$flags ord($gif{10});
        
$bitsPerPixel $flags 7;
        
$numberOfColors << ($bitsPerPixel+1);
        
$colorTableSize $numberOfColors;
        
$header subStr($gif6$colorTableSize);

        
// Image Descriptor + Table Based Image Data
        
$block subStr($gif13+$colorTableSize, -1);

        return array(
$header$block);
    }
}

?>