<?php
/**
* Class PixOfCake
* @author : Jay Salvat - http://jaysalvat.com
*
* Classe de gestion d'images
*
* - Exemple basique
* $Pix = new PixOfCake('picture.jpg');
* $Pix->size(200, 300)->rotate(40)->save()->show();
*
* - Exemple avec cache
* $Pix = new PixOfCake('picture.jpg', new PixOfCakeCache($param));
* $Pix->size(200, 300)->rotate(40)->show();
*/
class PixOfCake {
public $width, $height, $mime, $path;
private $image, $backup, $data;
private $background;
private $Cache;
const MIDDLE = 'middle';
const TOP = 'top';
const BOTTOM = 'bottom';
const LEFT = 'left';
const RIGHT = 'right';
public function __construct($path_or_data, PixOfCakeCache $Cache = null) {
if(!function_exists('imagecreatetruecolor')) {
throw new PixOfCakeException('Librairie GD introuvable');
}
if(file_exists($path_or_data)) {
$this->path = $path_or_data;
$this->data = null;
} else if (imagecreatefromstring($path_or_data)) {
$this->path = null;
$this->data = $path_or_data;
} else {
throw new PixOfCakeException('Données image illisibles');
}
if ($Cache) {
$this->Cache = $Cache;
if ($this->Cache->check($this)) {
return;
}
}
if($image = @imagecreatefromstring($this->data)) {
$mime = 'image/png';
} else {
$info = getimagesize($this->path);
$mime = $info['mime'];
switch($mime) {
case 'image/png' :
$image = imagecreatefrompng($this->path);
break;
case 'image/jpeg':
$image = imagecreatefromjpeg($this->path);
break;
default:
throw new PixOfCakeException('Format inconnu');
break;
}
}
$this->image = $image;
$this->backup = $image;
$this->width = imagesx($image);
$this->height = imagesy($image);
$this->mime = $mime;
$this->Cache = $Cache;
}
public function rotate($angle) {
if(!$this->image) {
return $this;
}
$this->image = imagerotate($this->image, $angle, $this->background, true);
imagealphablending($this->image, false);
imagesavealpha($this->image, true);
$this->width = imagesx($this->image);
$this->height = imagesy($this->image);
return $this;
}
public function maxSize($max) {
if(!$this->image) {
return $this;
}
if ($this->width > $this->height) {
return $this->size($max);
} else {
return $this->size(null, $max);
}
}
public function size($width, $height = null) {
if(!$this->image) {
return $this;
}
if(!$height && $width) {
$height = $this->height * $width / $this->width;
}
if($height && !$width) {
$width = $this->width * $height / $this->height;;
}
$temp = $this->getCanvas($width, $height);
imagecopyresampled($temp, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height);
$this->width = $width;
$this->height = $height;
$this->image = $temp;
return $this;
}
public function width($width) {
if(!$this->image) {
return $this;
}
return $this->size($width);
}
public function height($height) {
if(!$this->image) {
return $this;
}
return $this->size(null, $height);
}
public function crop($x, $y, $width, $height) {
if(!$this->image) {
return $this;
}
$temp = $this->getCanvas($width, $height);
imagecopy($temp, $this->image, 0, 0, $x, $y, $width, $height);
$this->width = $width;
$this->height = $height;
$this->image = $temp;
return $this;
}
public function thumbnail($width, $height = null, $mode = null) {
if(!$this->image) {
return $this;
}
if (!$height) {
$height = $width;
}
if (!$mode && is_string($height)) {
$mode = $height;
$height = $width;
}
if (isset($mode)) {
if ($this->width >= $this->height) {
if ($width <= $height) {
$w = $this->width / ($this->height / $height);
$h = $height;
} else {
$w = $width;
$h = $this->height / ($this->width / $width);
}
if ($mode == PixOfCake::LEFT) {
$left = 0;
} else if ($mode == PixOfCake::RIGHT) {
$left = -($w - $width);
} else {
$left = -(($w - $width) / 2);
}
$top = 0;
} else {
if ($width <= $height) {
$w = $width;
$h = $this->height / ($this->width / $width);
} else {
$w = $this->width / ($this->height / $height);
$h = $height;
}
if ($mode == PixOfCake::TOP) {
$top = 0;
} else if ($mode == PixOfCake::BOTTOM) {
$top = -($h - $height);
} else{
$top = -(($h - $height) / 2);
}
$left = 0;
}
} else {
if ($this->width >= $this->height) {
$w = $width;
$h = $this->height / ($this->width / $width);
$left = 0;
$top = -(($h - $height) / 2);
} else {
$w = $this->width / ($this->height / $height);
$h = $height;
$left = -(($w - $width) / 2);
$top = 0;
}
}
$temp = $this->getCanvas($width, $height);
imagecopyresampled($temp, $this->image, $left, $top, 0, 0, $w, $h, $this->width, $this->height);
$this->width = $width;
$this->height = $height;
$this->image = $temp;
return $this;
}
public function save($path, $quality = 80) {
if(!$this->image) {
return $this;
}
switch(strtolower(pathinfo($path, PATHINFO_EXTENSION))) {
case 'png' :
$success = imagepng($this->image, $path);
break;
case 'jpeg': case 'jpg' :
$success = imagejpeg($this->image, $path, $quality);
break;
default:
throw new PixOfCakeException('Format inconnu');
break;
}
if (!$success) {
throw new PixOfCakeException("L'image (ou son cache) n'a pu être sauvegardé");
}
return $this;
}
public function show($format = null, $quality = 80, $header = true) {
if(!$this->image) {
return $this;
}
if (is_int($format)) {
$quality = $format;
$format = $this->mime;
} else if (!$format) {
$format = $this->mime;
}
if ($header) {
header("Content-type: ".$format);
}
switch($format) {
case 'image/png' :
imagepng($this->image, null);
break;
case 'image/jpeg':
imagejpeg($this->image, null, $quality);
break;
default:
throw new PixOfCakeException('Format inconnu');
break;
}
if ($this->Cache) {
$this->Cache->save($this);
}
return $this;
}
public function data($format = null, $quality = 80) {
ob_start();
$this->show($format, $quality, false);
$data = ob_get_contents();
ob_end_clean();
return $data;
}
public function restore() {
if(!$this->image) {
return $this;
}
$this->image = $this->backup;
return $this;
}
public function destroy() {
if(!$this->image) {
return $this;
}
imagedestroy($this->image);
imagedestroy($this->backup);
}
public function background($color, $alpha = 0) {
if(!$this->image) {
return $this;
}
$color = str_replace('#', '', $color);
$r = hexdec(substr($color, 0, 2));
$g = hexdec(substr($color, 2, 2));
$b = hexdec(substr($color, 4, 2));
$this->background = imagecolorallocatealpha($this->image, $r, $g, $b, $alpha);
return $this;
}
private function getCanvas($width, $height) {
$canvas = imagecreatetruecolor($width, $height);
imagefill($canvas, 0, 0, $this->background);
imagealphablending($canvas, false);
imagesavealpha($canvas, true);
return $canvas;
}
public function __toString() {
return $this->data();
}
}
class PixOfCakeCache {
private $path, $file;
private $folder = 'cache/';
public function __construct($file = null, $data = array()) {
$this->file = $file;
$this->namespace($data);
}
public function namespace($data = array()) {
if (!empty($data)) {
ksort($data);
$values = '';
foreach($data as $k => $v) {
$values .= $k.':'.$v.':';
}
$prefix = md5($values);
$this->computePath($this->folder, $prefix.$this->file);
}
return $this;
}
public function valid($file) {
if (file_exists($file) && file_exists($this->path)) {
if (filemtime($this->path) > filemtime($file)) {
return true;
}
}
return false;
}
public function check(PixOfCake $PixOfCake) {
if (!$this->file) {
$this->computePath($this->folder, $PixOfCake->path);
}
if ($this->valid($PixOfCake->path)) {
$this->show();
return true;
} else {
$this->destroy();
return false;
}
}
public function show() {
$PixOfCake = new PixOfCake($this->path);
$PixOfCake->show()->destroy();
return $this;
}
public function save(PixOfCake $PixOfCake) {
try {
$PixOfCake->save($this->path)->destroy();
} catch(PixOfCakeException $e) {
throw new PixOfCakeCacheException('Cache impossible à écrire');
}
return $this;
}
public function destroy() {
if (file_exists($this->path)) {
unlink($this->path);
}
return $this;
}
public function folder($folder) {
if (!is_dir($folder)) {
throw new PixOfCakeCacheException("Le dossier de Cache n'existe pas");
}
$this->computePath($folder, $this->file);
return $this;
}
private function computePath($folder, $file) {
$this->folder = $folder;
$this->file = $file;
$this->path = str_replace('//', '/', $folder."/".str_replace('/', '-', $file));
return $this;
}
}
class PixOfCakeException extends Exception {}
class PixOfCakeCacheException extends Exception {}
?>