天天看點

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

class PicThumb{ // class start

private $_log = null; // log file

private $_handler = null; // 進行圖檔處理的程式,imagemagick/gd庫

private $_type = 'fit'; // fit or crop

private $_source = null; // 原圖路徑

private $_dest = null; // 縮略圖路徑

private $_watermark = null; // 水印圖檔

private $_opacity = 75; // 水印圖片透明度,gd庫不支援

private $_gravity = 'SouthEast'; // 水印擺放位置 NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast

private $_geometry = '+10+10'; // 水印定位,gd庫不支援

private $_croppos = 'TL'; // 截圖的位置 TL TM TR ML MM MR BL BM BR

private $_bgcolor = null; // 填充的背景色

private $_quality = 90; // 生成的圖檔品質

private $_width = null; // 指定區域寬度

private $_height = null; // 指定區域高度

// 初始化

public function __construct($logfile=''){

if($logfile!=''){

$this->_log = $logfile;

}

}

// 設定參數

public function set_config($param=array()){

$this->_handler = $this->exists($param, 'handler')? strtolower($param['handler']) : null;

$this->_type = $this->exists($param, 'type')? strtolower($param['type']) : 'fit';

$this->_watermark = $this->exists($param, 'watermark')? $param['watermark'] : null;

$this->_opacity = $this->exists($param, 'opacity')? $param['opacity'] : 75;

$this->_gravity = $this->exists($param, 'gravity')? $param['gravity'] : 'SouthEast';

$this->_geometry = $this->exists($param, 'geometry')? $param['geometry'] : '+10+10';

$this->_croppos = $this->exists($param, 'croppos')? $param['croppos'] : 'TL';

$this->_bgcolor = $this->exists($param, 'bgcolor')? $param['bgcolor'] : null;

$this->_quality = $this->exists($param, 'quality')? $param['quality'] : 90;

$this->_width = $this->exists($param, 'width')? $param['width'] : null;

$this->_height = $this->exists($param, 'height')? $param['height'] : null;

}

public function create_thumb($source, $dest){

// 檢查使用的handler是否已安裝

if(!$this->check_handler()){

$this->to_log('handler not installed');

return false;

}

// 判斷區域寬高是否正确

if(!is_numeric($this->_width) || !is_numeric($this->_height) || $this->_width<=0 || $this->_height<=0){

$this->to_log('width or height invalid');

return false;

}

// 判斷源檔案是否存在

if(!file_exists($source)){

$this->to_log($source.' not exists');

return false;

}

// 建立目标檔案路徑

if(!$this->create_dirs($dest)){

$this->to_log(dirname($dest).' create fail');

return false;

}

$this->_source = $source; // 源檔案

$this->_dest = $dest; // 目标檔案

// 處理圖檔

switch($this->_type){

case 'fit':

if($this->_handler=='imagemagick'){

return $this->fit();

}else{

return $this->gd_fit();

}

break;

case 'crop':

if($this->_handler=='imagemagick'){

return $this->crop();

}else{

return $this->gd_crop();

}

break;

default:

$this->to_log($this->_type.' not fit and crop');

return false;

}

}

private function fit(){

// 判斷是否填充背景

$bgcolor = ($this->_bgcolor!=null)?

sprintf(" -background '%s' -gravity center -extent '%sx%s' ", $this->_bgcolor, $this->_width, $this->_height) : "";

// 判斷是否要轉為RGB

$source_info = getimagesize($this->_source);

$colorspace = (!isset($source_info['channels']) || $source_info['channels']!=3)? ' -colorspace RGB ' : '';

// 指令行

$cmd = sprintf("convert -resize '%sx%s' '%s' %s -quality %s %s '%s'", $this->_width, $this->_height, $this->_source, $bgcolor, $this->_quality, $colorspace, $this->_dest);

// 記錄執行的指令

$this->to_log($cmd);

// 執行指令

exec($cmd);

// 添加水印

$this->add_watermark($this->_dest);

return is_file($this->_dest)? true : false;

}

private function crop(){

// 擷取生成的圖檔尺寸

list($pic_w, $pic_h) = $this->get_size();

// 擷取截圖的偏移量

list($offset_w, $offset_h) = $this->get_crop_offset($pic_w, $pic_h);

// 判斷是否要轉為RGB

$source_info = getimagesize($this->_source);

$colorspace = (!isset($source_info['channels']) || $source_info['channels']!=3)? ' -colorspace RGB ' : '';

// 指令行

$cmd = sprintf("convert -resize '%sx%s' '%s' -quality %s %s -crop %sx%s+%s+%s +repage '%s'", $pic_w, $pic_h, $this->_source, $this->_quality, $colorspace, $this->_width, $this->_height, $offset_w, $offset_h, $this->_dest);

// 記錄執行的指令

$this->to_log($cmd);

// 執行指令

exec($cmd);

// 添加水印

$this->add_watermark($this->_dest);

return is_file($this->_dest)? true : false;

}

private function gd_fit(){

// 擷取生成的圖檔尺寸

list($pic_w, $pic_h) = $this->get_size();

list($owidth, $oheight, $otype) = getimagesize($this->_source);

switch($otype){

case 1: $source_img = imagecreatefromgif($this->_source); break;

case 2: $source_img = imagecreatefromjpeg($this->_source); break;

case 3: $source_img = imagecreatefrompng($this->_source); break;

default: return false;

}

// 按比例縮略/拉伸圖檔

$new_img = imagecreatetruecolor($pic_w, $pic_h);

imagecopyresampled($new_img, $source_img, 0, 0, 0, 0, $pic_w, $pic_h, $owidth, $oheight);

// 判斷是否填充背景

if($this->_bgcolor!=null){

$bg_img = imagecreatetruecolor($this->_width, $this->_height);

$rgb = $this->hex2rgb($this->_bgcolor);

$bgcolor =imagecolorallocate($bg_img, $rgb['r'], $rgb['g'], $rgb['b']);

imagefill($bg_img, 0, 0, $bgcolor);

imagecopy($bg_img, $new_img, (int)(($this->_width-$pic_w)/2), (int)(($this->_height-$pic_h)/2), 0, 0, $pic_w, $pic_h);

$new_img = $bg_img;

}

// 擷取目标圖檔的類型

$dest_ext = $this->get_file_ext($this->_dest);

// 生成圖檔

switch($dest_ext){

case 1: imagegif($new_img, $this->_dest, $this->_quality); break;

case 2: imagejpeg($new_img, $this->_dest, $this->_quality); break;

case 3: imagepng($new_img, $this->_dest, (int)(($this->_quality-1)/10)); break;

}

if(isset($source_img)){

imagedestroy($source_img);

}

if(isset($new_img)){

imagedestroy($new_img);

}

// 添加水印

$this->add_watermark($this->_dest);

return is_file($this->_dest)? true : false;

}

private function gd_crop(){

// 擷取生成的圖檔尺寸

list($pic_w, $pic_h) = $this->get_size();

// 擷取截圖的偏移量

list($offset_w, $offset_h) = $this->get_crop_offset($pic_w, $pic_h);

list($owidth, $oheight, $otype) = getimagesize($this->_source);

switch($otype){

case 1: $source_img = imagecreatefromgif($this->_source); break;

case 2: $source_img = imagecreatefromjpeg($this->_source); break;

case 3: $source_img = imagecreatefrompng($this->_source); break;

default: return false;

}

// 按比例縮略/拉伸圖檔

$tmp_img = imagecreatetruecolor($pic_w, $pic_h);

imagecopyresampled($tmp_img, $source_img, 0, 0, 0, 0, $pic_w, $pic_h, $owidth, $oheight);

// 裁剪圖檔

$new_img = imagecreatetruecolor($this->_width, $this->_height);

imagecopyresampled($new_img, $tmp_img, 0, 0, $offset_w, $offset_h, $this->_width, $this->_height, $this->_width, $this->_height);

// 擷取目标圖檔的類型

$dest_ext = $this->get_file_ext($this->_dest);

// 生成圖檔

switch($dest_ext){

case 1: imagegif($new_img, $this->_dest, $this->_quality); break;

case 2: imagejpeg($new_img, $this->_dest, $this->_quality); break;

case 3: imagepng($new_img, $this->_dest, (int)(($this->_quality-1)/10)); break;

}

if(isset($source_img)){

imagedestroy($source_img);

}

if(isset($tmp_img)){

imagedestroy($tmp_img);

}

if(isset($new_img)){

imagedestroy($new_img);

}

// 添加水印

$this->add_watermark($this->_dest);

return is_file($this->_dest)? true : false;

}

private function get_size(){

list($owidth, $oheight) = getimagesize($this->_source);

$width = (int)($this->_width);

$height = (int)($this->_height);

switch($this->_type){

case 'fit':

$pic_w = $width;

$pic_h = (int)($pic_w*$oheight/$owidth);

if($pic_h>$height){

$pic_h = $height;

$pic_w = (int)($pic_h*$owidth/$oheight);

}

break;

case 'crop':

if($owidth>$oheight){

$pic_h = $height;

$pic_w = (int)($pic_h*$owidth/$oheight);

}else{

$pic_w = $width;

$pic_h = (int)($pic_w*$oheight/$owidth);

}

break;

}

return array($pic_w, $pic_h);

}

private function get_crop_offset($pic_w, $pic_h){

$offset_w = 0;

$offset_h = 0;

switch(strtoupper($this->_croppos)){

case 'TL':

$offset_w = 0;

$offset_h = 0;

break;

case 'TM':

$offset_w = (int)(($pic_w-$this->_width)/2);

$offset_h = 0;

break;

case 'TR':

$offset_w = (int)($pic_w-$this->_width);

$offset_h = 0;

break;

case 'ML':

$offset_w = 0;

$offset_h = (int)(($pic_h-$this->_height)/2);

break;

case 'MM':

$offset_w = (int)(($pic_w-$this->_width)/2);

$offset_h = (int)(($pic_h-$this->_height)/2);

break;

case 'MR':

$offset_w = (int)($pic_w-$this->_width);

$offset_h = (int)(($pic_h-$this->_height)/2);

break;

case 'BL':

$offset_w = 0;

$offset_h = (int)($pic_h-$this->_height);

break;

case 'BM':

$offset_w = (int)(($pic_w-$this->_width)/2);

$offset_h = (int)($pic_h-$this->_height);

break;

case 'BR':

$offset_w = (int)($pic_w-$this->_width);

$offset_h = (int)($pic_h-$this->_height);

break;

}

return array($offset_w, $offset_h);

}

private function add_watermark($dest){

if($this->_watermark!=null && file_exists($this->_watermark) && file_exists($dest)){

list($owidth, $oheight, $otype) = getimagesize($dest);

list($w, $h, $wtype) = getimagesize($this->_watermark);

// 水印圖比原圖要小才加水印

if($w<=$owidth && $h<=$oheight){

if($this->_handler=='imagemagick'){ // imagemagick 添加水印

$cmd = sprintf("composite -gravity %s -geometry %s -dissolve %s '%s' %s %s", $this->_gravity, $this->_geometry, $this->_opacity, $this->_watermark, $dest, $dest);

$this->to_log($cmd);

exec($cmd);

}else{ // gd 添加水印

switch($wtype){

case 1: $water_img = imagecreatefromgif($this->_watermark); break;

case 2: $water_img = imagecreatefromjpeg($this->_watermark); break;

case 3: $water_img = imagecreatefrompng($this->_watermark); break;

default: return false;

}

switch($otype){

case 1: $dest_img = imagecreatefromgif($dest); break;

case 2: $dest_img = imagecreatefromjpeg($dest); break;

case 3: $dest_img = imagecreatefrompng($dest); break;

default: return false;

}

// 水印位置

switch(strtolower($this->_gravity)){

case 'northwest':

$posX = 0;

$posY = 0;

break;

case 'north':

$posX = ($owidth - $w) / 2;

$posY = 0;

break;

case 'northeast':

$posX = $owidth - $w;

$posY = 0;

break;

case 'west':

$posX = 0;

$posY = ($oheight - $h) / 2;

break;

case 'center':

$posX = ($owidth - $w) / 2;

$posY = ($oheight - $h) / 2;

break;

case 'east':

$posX = $owidth - $w;

$posY = ($oheight - $h) / 2;

break;

case 'southwest':

$posX = 0;

$posY = $oheight - $h;

break;

case 'south':

$posX = ($owidth - $w) / 2;

$posY = $oheight - $h;

break;

case 'southeast':

$posX = $owidth - $w;

$posY = $oheight - $h;

break;

}

imagealphablending($dest_img, true);

imagecopy($dest_img, $water_img, $posX, $posY, 0, 0, $w, $h);

switch($otype){

case 1:imagegif($dest_img, $dest, $this->_quality); break;

case 2:imagejpeg($dest_img, $dest, $this->_quality); break;

case 3:imagepng($dest_img, $dest, (int)(($this->_quality-1)/10)); break;

}

if(isset($water_img)){

imagedestroy($water_img);

}

if(isset($dest_img)){

imagedestroy($dest_img);

}

}

}

}

}

private function check_handler(){

$handler = $this->_handler;

if(!in_array($handler, array('imagemagick', 'gd', null))){

return false;

}

// 檢查是否有安裝imagemagick

$imagemagick_installed = strstr(shell_exec('convert -version'),'Version: ImageMagick')!=''? true : false;

// 檢查是否有安裝gd庫

$gd_installed = function_exists('gd_info')? true : false;

switch($handler){

case 'imagemagick':

return $imagemagick_installed;

break;

case 'gd':

return $gd_installed;

break;

case null:

if($imagemagick_installed){

$this->_handler = 'imagemagick';

return true;

}

if($gd_installed){

$this->_handler = 'gd';

return true;

}

break;

}

return false;

}

private function create_dirs($dest){

if(!is_dir(dirname($dest))){

return mkdir(dirname($dest), 0777, true);

}

return true;

}

private function exists($obj,$key=''){

if($key==''){

return isset($obj) && !empty($obj);

}else{

$keys = explode('.',$key);

for($i=0,$max=count($keys); $i

if(isset($obj[$keys[$i]])){

$obj = $obj[$keys[$i]];

}else{

return false;

}

}

return isset($obj) && !empty($obj);

}

}

private function to_log($msg){

if($this->_log){

$msg = '['.date('Y-m-d H:i:s').']'.$msg."rn";

file_put_contents($this->_log, $msg, FILE_APPEND);

}

}

private function hex2rgb($hexcolor){

$color = str_replace('#', '', $hexcolor);

if (strlen($color) > 3) {

$rgb = array(

'r' => hexdec(substr($color, 0, 2)),

'g' => hexdec(substr($color, 2, 2)),

'b' => hexdec(substr($color, 4, 2))

);

} else {

$r = substr($color, 0, 1) . substr($color, 0, 1);

$g = substr($color, 1, 1) . substr($color, 1, 1);

$b = substr($color, 2, 1) . substr($color, 2, 1);

$rgb = array(

'r' => hexdec($r),

'g' => hexdec($g),

'b' => hexdec($b)

);

}

return $rgb;

}

private function get_file_ext($file){

$filename = basename($file);

list($name, $ext)= explode('.', $filename);

$ext_type = 0;

switch(strtolower($ext)){

case 'jpg':

case 'jpeg':

$ext_type = 2;

break;

case 'gif':

$ext_type = 1;

break;

case 'png':

$ext_type = 3;

break;

}

return $ext_type;

}

} // class end

?>

define('ROOT', dirname(__FILE__));

require(ROOT."/PicThumb.class.php");

$logfile = ROOT.'/PicThumb.log';

$source1 = ROOT.'/pic/source.jpg';

$dest1 = ROOT.'/pic/1.jpg';

$dest2 = ROOT.'/pic/2.gif';

$dest3 = ROOT.'/pic/3.png';

$source2 = ROOT.'/pic/source_cmyk.jpg';

$dest4 = ROOT.'/pic/4.jpg';

$dest5 = ROOT.'/pic/5.gif';

$dest6 = ROOT.'/pic/6.png';

$watermark = ROOT.'/pic/watermark.png';

// 按比例生成縮略圖

$param = array(

'type' => 'fit',

'width' => 100,

'height' => 100,

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source1, $dest1);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

// 按比例生成縮略圖,不足部分用#FF0000填充

$param = array(

'type' => 'fit',

'width' => 100,

'height' => 100,

'bgcolor' => '#FFFF00'

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source1, $dest2);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

// 裁剪250x250的縮略圖,裁剪位置是底部中間,水印位置西南,透明度50

$param = array(

'type' => 'crop',

'croppos' => 'BM',

'width' => 250,

'height' => 250,

'watermark' => $watermark,

'opacity' => 50,

'gravity' => 'SouthWest'

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source1, $dest3);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

// 按比例生成縮略圖 CMYK格式

$param = array(

'type' => 'fit',

'width' => 100,

'height' => 100,

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source2, $dest4);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

// 按比例生成縮略圖,不足部分用#FF0000填充 CMYK格式

$param = array(

'type' => 'fit',

'width' => 100,

'height' => 100,

'bgcolor' => '#FFFF00'

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source2, $dest5);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

// 裁剪250x250的縮略圖,裁剪位置是底部中間,水印位置西南,透明度50 CMYK格式

$param = array(

'type' => 'crop',

'croppos' => 'BM',

'width' => 250,

'height' => 250,

'watermark' => $watermark,

'opacity' => 50,

'gravity' => 'SouthWest'

);

$obj = new PicThumb($logfile);

$obj->set_config($param);

$flag = $obj->create_thumb($source2, $dest6);

if($flag){

echo '

php gd庫和imagemagick,php實作的支援imagemagick及gd庫兩種處理的縮略圖生成類

';

}else{

echo 'create thumb fail';

}

?>