<?php

class Image {
    public static 
$cacheDir "cache/images";
    private 
$gd;
    private 
$hash;
    private 
$file;
    private 
$operations;

    public function 
__construct($file="") {
        
$this->gd null;
        
$this->hash "";
        
$this->operations = array();
        
$this->file=$file;
    }
    
    public static function 
file($file) {
        
$directory Image::$cacheDir;
        if (!
file_exists($directory))
            
mkdir($directory); 
        for (
$i=0$i<5$i++) {
            
$c $file[$i];
            
$directory.="/$c";
            if (!
file_exists($directory)) {
                
mkdir($directory);
            }
        }
        
$file $directory."/".substr($file,5);
        return 
$file;
    }

    public function 
fromFile($file) {
        
$this->file $file;
        return 
$this;
    }

    public function 
openFile() {
        
$file $this->file;
        if (!
$this->fromJpeg($file))
        if (!
$this->fromGif($file))
            
$this->fromPng($file);
        return 
$this;
    }

    public function 
fromJpeg($file) {
        
$this->file $file;
        
$this->gd imagecreatefromjpeg($file);
        return (
$this->gd !== false);
    }
    
    public function 
fromGif($file) {
        
$this->file $file;
        
$this->gd imagecreatefromgif($file);
        return (
$this->gd !== false);
    }

    public function 
fromPng($file) {
        
$this->file $file;
        
$this->gd imagecreatefromgif($file);
        return (
$this->gd !== false);
    }

    public function 
resize($w$h$bg=0xFFFFFF) {
        
$this->operations[] = array("resize",$w,$h,$bg);
        return 
$this;
    }

    public function 
forceResize($w$h$bg=0xFFFFFF) {
        
$this->operations[] = array("forceResize",$w,$h,$bg);
        return 
$this;
    }

    public function 
scaleResize($w$h$bg=0xFFFFFF) {
        
$this->operations[] = array("scaleResize",$w,$h,$bg);
        return 
$this;
    }

    public function 
cropResize($w$h$bg=0xFFFFFF) {
        
$this->operations[] = array("cropResize",$w,$h,$bg);
        return 
$this;
    }

    public function 
_resize($w=null,$h=null,$bg,$force=false,$rescale=false,$crop=false) {
        
$width imagesx($this->gd);
        
$height imagesy($this->gd);
        
$scale 1.0;
        if (!
$force || $crop) {
            if (
$w!=null && $width>$w) {
                
$scale $width/$w;
            }
            if (
$h!=null && $height>$h) {
                if (
$height/$h $scale)
                    
$scale $height/$h;
            }
        } else {
            if (
$w!=null) {
                
$scale $width/$w;
                
$new_width $w;
            }
            if (
$h!=null) {
                if (
$w!=null && $rescale)
                    
$scale max($scale,$height/$h);
                else
                    
$scale $height/$h;
                
$new_height $h;
            }
        }
        if (!
$force || $w==null || $rescale)
            
$new_width = (int)($width/$scale);
        if (!
$force || $h==null || $rescale)
            
$new_height = (int)($height/$scale);

        if (
$w == null || $crop)
            
$w $new_width;
        if (
$h == null || $crop)
            
$h $new_height;

        
$n imagecreatetruecolor($w$h);

        if (
$bg!="transparent") {
            
imagefill($n00$bg);
        } else {
            
imagealphablending($n,false);
            
$color imagecolorallocatealpha($n000127);
            
imagefill($n,0,0,$color);
            
imagesavealpha($n,true);
        }
        
imagecopyresampled($n$this->gd, ($w-$new_width)/2, ($h-$new_height)/200$new_width$new_height$width$height);
        
imagedestroy($this->gd);
        
$this->gd $n;
    }

    public function 
cacheFile($type "jpg"$quality 80) {
        
$hash=     $this->file." ";
        
$hash.=    filectime($this->file)." ";
        
$hash.= serialize($this->operations)." ".$type." ".$quality;
        
$this->hash sha1($hash);
        
$file Image::file($this->hash.".".$type);
        if (!
file_exists($file)) {
            
$this->save($file$type$quality);
        }
        return 
$file;
    }

    public function 
save($file$type="jpg"$quality 80) {
        
$this->openFile();

        foreach (
$this->operations as $o) {
            switch (
$o[0]) {
                case 
"resize":
                    
$this->_resize($o[1],$o[2],$o[3]);
                break;
                case 
"forceResize":
                    
$this->_resize($o[1],$o[2],$o[3], true);
                break;
                case 
"scaleResize":
                    
$this->_resize($o[1],$o[2],$o[3], truetrue);
                break;
                case 
"cropResize":
                    
$this->_resize($o[1],$o[2],$o[3], truetruetrue);
                break;
            }
        }
        if (
$type=="jpg"
            
imagejpeg($this->gd$file$quality);
        if (
$type=="gif")
            
imagegif($this->gd$file);
        if (
$type=="png")
            
imagepng($this->gd$file);
    }

    public function 
jpeg($quality 80) {
        return 
$this->cacheFile("jpg"$quality);
    }

    public function 
gif() {
        return 
$this->cacheFile("gif");
    }

    public function 
png() {
        return 
$this->cacheFile("png");
    }
}

function 
Image($file="") {
    return new 
Image($file);
}