当前位置:首页 > PHP教程 > php高级应用 > 列表

浅谈php扩展imagick

发布:smiling 来源: PHP粉丝网  添加日期:2021-01-31 18:32:45 浏览: 评论:0 

imagick是一个可以供PHP调用ImageMagick功能的PHP扩展。使用这个扩展可以使PHP具备和ImageMagick相同的功能。

PHP建图通常都用GD库,因为是内置的不需要在服务器上额外安装插件,所以用起来比较省心,但是如果你的程序主要的功能就是处理图像,那麼就不建议用GD了,因为GD不但低效能而且能力也比较弱,佔用的系统资源也颇多,另外GD的creatfrom也有bug,而imagick却是一个很好的替代品,为此最近把我的一个项目由GD改成了imagick,但是改完之后出现了一些状况在此分享给大家.

首先说一下我这边出现的状况:

状况一:需要重写图像操作class

状况二:imagick多线程时会导致cpu使用率暴增到100%

在此顺便提一下imagick在centos6.4的安装方法:

1、安装ImageMagick

代码如下:

  1. wget http://soft.vpser.net/web/imagemagick/ImageMagick-6.7.1-2.tar.gz 
  2. tar zxvf ImageMagick-6.7.1-2.tar.gz 
  3. cd ImageMagick-6.7.1-2/ 
  4. ./configure --prefix=/usr/local/imagemagick --disable-openmp 
  5. make && make install 
  6. ldconfig 

测试ImageMagick是否可以正常运行:

代码如下:

/usr/local/imagemagick/bin/convert -version

2、安装PHP扩展:imagick

代码如下:

  1. wget http://pecl.php.net/get/imagick-3.0.1.tgz 
  2. tar zxvf imagick-3.0.1.tgz 
  3. cd imagick-3.0.1/ 
  4. /usr/local/php/bin/phpize 
  5. ./configure --with-php-config=/usr/local/php/bin/php-config --with-imagick=/usr/local/imagemagick 
  6. make && make install 
  7. ldconfig 
  8. vi /usr/local/php/etc/php.ini 

添加:extension = "imagick.so"

重启lnmp,代码如下:

/root/lnmp reload

接下来我们针对上述两个状况分别提出解决办法:

状况一的解决办法如下:

  1. /** 
  2.     Imagick图像处理类 
  3.     用法: 
  4.         //引入Imagick物件 
  5.         if(!defined('CLASS_IMAGICK')){require(Inc.'class_imagick.php');} 
  6.         $Imagick=new class_imagick(); 
  7.         $Imagick->open('a.gif'); 
  8.         $Imagick->resize_to(100,100,'scale_fill'); 
  9.         $Imagick->add_text('1024i.com',10,20); 
  10.         $Imagick->add_watermark('1024i.gif',10,50); 
  11.         $Imagick->save_to('x.gif'); 
  12.         unset($Imagick); 
  13. /**/ 
  14. define('CLASS_IMAGICK',TRUE); 
  15. class class_imagick{ 
  16.     private $image=null; 
  17.     private $type=null; 
  18.     // 构造 
  19.     public function __construct(){} 
  20.     // 析构 
  21.     public function __destruct(){ 
  22.         if($this->image!==null){$this->image->destroy();} 
  23.     } 
  24.     // 载入图像 
  25.     public function open($path){ 
  26.         if(!file_exists($path)){ 
  27.             $this->image=null; 
  28.             return ; 
  29.         } 
  30.         $this->image=new Imagick($path); 
  31.         if($this->image){ 
  32.             $this->type=strtolower($this->image->getImageFormat()); 
  33.         } 
  34.         $this->image->stripImage(); 
  35.         return $this->image; 
  36.     } 
  37.     /** 
  38.         图像裁切 
  39.     /**/ 
  40.     public function crop($x=0,$y=0,$width=null,$height=null){ 
  41.         if($width==null) $width=$this->image->getImageWidth()-$x
  42.         if($height==null) $height=$this->image->getImageHeight()-$y
  43.         if($width<=0 || $height<=0) return
  44.         if($this->type=='gif'){ 
  45.             $image=$this->image; 
  46.             $canvas=new Imagick(); 
  47.             $images=$image->coalesceImages(); 
  48.             foreach($images as $frame){ 
  49.                 $img=new Imagick(); 
  50.                 $img->readImageBlob($frame); 
  51.                 $img->cropImage($width,$height,$x,$y); 
  52.                 $canvas->addImage($img); 
  53.                 $canvas->setImageDelay($img->getImageDelay()); 
  54.                 $canvas->setImagePage($width,$height,0,0); 
  55.             } 
  56.             $image->destroy(); 
  57.             $this->image=$canvas
  58.         }else
  59.             $this->image->cropImage($width,$height,$x,$y); 
  60.         } 
  61.     } 
  62.     /** 
  63.         更改图像大小 
  64.         参数: 
  65.             $width:新的宽度 
  66.             $height:新的高度 
  67.             $fit: 适应大小 
  68.                 'force': 把图像强制改为$width X $height 
  69.                 'scale': 按比例在$width X $height内缩放图片,结果不完全等於$width X $height 
  70.                 'scale_fill':按比例在$width X $height内缩放图片,没有像素的地方填充顏色$fill_color=array(255,255,255)(红,绿,蓝,透明度[0不透明-127全透明]) 
  71.                 其他:智能模式,缩放图片并从正中裁切$width X $height的大小 
  72.         注意: 
  73.             $fit='force','scale','scale_fill'时输出完整图像 
  74.             $fit=图像方位时输出指定位置部份的图像 
  75.         字母与图像的对应关系如下: 
  76.             north_west   north   north_east 
  77.             west         center        east 
  78.             south_west   south   south_east 
  79.     /**/ 
  80.     public function resize_to($width=100,$height=100,$fit='center',$fill_color=array(255,255,255,0)){ 
  81.         switch($fit){ 
  82.         case 'force'
  83.             if($this->type=='gif'){ 
  84.                 $image=$this->image; 
  85.                 $canvas=new Imagick(); 
  86.                 $images=$image->coalesceImages(); 
  87.                 foreach($images as $frame){ 
  88.                     $img=new Imagick(); 
  89.                     $img->readImageBlob($frame); 
  90.                     $img->thumbnailImage($width,$height,false); 
  91.                     $canvas->addImage($img); 
  92.                     $canvas->setImageDelay($img->getImageDelay()); 
  93.                 } 
  94.                 $image->destroy(); 
  95.                 $this->image=$canvas
  96.             }else
  97.                 $this->image->thumbnailImage($width,$height,false); 
  98.             } 
  99.             break
  100.         case 'scale'
  101.             if($this->type=='gif'){ 
  102.                 $image=$this->image; 
  103.                 $images=$image->coalesceImages(); 
  104.                 $canvas=new Imagick(); 
  105.                 foreach($images as $frame){ 
  106.                     $img=new Imagick(); 
  107.                     $img->readImageBlob($frame); 
  108.                     $img->thumbnailImage($width,$height,true); 
  109.                     $canvas->addImage($img); 
  110.                     $canvas->setImageDelay($img->getImageDelay()); 
  111.                 } 
  112.                 $image->destroy(); 
  113.                 $this->image=$canvas
  114.             }else
  115.                 $this->image->thumbnailImage($width,$height,true); 
  116.             } 
  117.             break
  118.         case 'scale_fill'
  119.             $size=$this->image->getImagePage(); 
  120.             $src_width=$size['width']; 
  121.             $src_height=$size['height']; 
  122.             $x=0; 
  123.             $y=0; 
  124.             $dst_width=$width
  125.             $dst_height=$height
  126.             if($src_width*$height > $src_height*$width){ 
  127.                 $dst_height=intval($width*$src_height/$src_width); 
  128.                 $y=intval(($height-$dst_height)/2); 
  129.             }else
  130.                 $dst_width=intval($height*$src_width/$src_height); 
  131.                 $x=intval(($width-$dst_width)/2); 
  132.             } 
  133.             $image=$this->image; 
  134.             $canvas=new Imagick(); 
  135.             $color='rgba('.$fill_color[0].','.$fill_color[1].','.$fill_color[2].','.$fill_color[3].')'
  136.             if($this->type=='gif'){ 
  137.                 $images=$image->coalesceImages(); 
  138.                 foreach($images as $frame){ 
  139.                     $frame->thumbnailImage($width,$height,true); 
  140.                     $draw=new ImagickDraw(); 
  141.                     $draw->composite($frame->getImageCompose(),$x,$y,$dst_width,$dst_height,$frame); 
  142.                     $img=new Imagick(); 
  143.                     $img->newImage($width,$height,$color,'gif'); 
  144.                     $img->drawImage($draw); 
  145.                     $canvas->addImage($img); 
  146.                     $canvas->setImageDelay($img->getImageDelay()); 
  147.                     $canvas->setImagePage($width,$height,0,0); 
  148.                 } 
  149.             }else
  150.                 $image->thumbnailImage($width,$height,true); 
  151.                 $draw=new ImagickDraw(); 
  152.                 $draw->composite($image->getImageCompose(),$x,$y,$dst_width,$dst_height,$image); 
  153.                 $canvas->newImage($width,$height,$color,$this->get_type()); 
  154.                 $canvas->drawImage($draw); 
  155.                 $canvas->setImagePage($width,$height,0,0); 
  156.             } 
  157.             $image->destroy(); 
  158.             $this->image=$canvas
  159.             break
  160.         default
  161.             $size=$this->image->getImagePage(); 
  162.             $src_width=$size['width']; 
  163.             $src_height=$size['height']; 
  164.             $crop_x=0; 
  165.             $crop_y=0; 
  166.             $crop_w=$src_width
  167.             $crop_h=$src_height
  168.             if($src_width*$height > $src_height*$width){ 
  169.                 $crop_w=intval($src_height*$width/$height); 
  170.             }else
  171.                 $crop_h=intval($src_width*$height/$width); 
  172.             } 
  173.             switch($fit){ 
  174.                 case 'north_west'
  175.                     $crop_x=0; 
  176.                     $crop_y=0; 
  177.                     break
  178.                 case 'north'
  179.                     $crop_x=intval(($src_width-$crop_w)/2); 
  180.                     $crop_y=0; 
  181.                     break
  182.                 case 'north_east'
  183.                     $crop_x=$src_width-$crop_w
  184.                     $crop_y=0; 
  185.                     break
  186.                 case 'west'
  187.                     $crop_x=0; 
  188.                     $crop_y=intval(($src_height-$crop_h)/2); 
  189.                     break
  190.                 case 'center'
  191.                     $crop_x=intval(($src_width-$crop_w)/2); 
  192.                     $crop_y=intval(($src_height-$crop_h)/2); 
  193.                     break
  194.                 case 'east'
  195.                     $crop_x=$src_width-$crop_w
  196.                     $crop_y=intval(($src_height-$crop_h)/2); 
  197.                     break
  198.                 case 'south_west'
  199.                     $crop_x=0; 
  200.                     $crop_y=$src_height-$crop_h
  201.                     break
  202.                 case 'south'
  203.                     $crop_x=intval(($src_width-$crop_w)/2); 
  204.                     $crop_y=$src_height-$crop_h
  205.                     break
  206.                 case 'south_east'
  207.                     $crop_x=$src_width-$crop_w
  208.                     $crop_y=$src_height-$crop_h
  209.                     break
  210.                 default
  211.                     $crop_x=intval(($src_width-$crop_w)/2); 
  212.                     $crop_y=intval(($src_height-$crop_h)/2); 
  213.             } 
  214.             $image=$this->image; 
  215.             $canvas=new Imagick(); 
  216.             if($this->type=='gif'){ 
  217.                 $images=$image->coalesceImages(); 
  218.                 foreach($images as $frame){ 
  219.                     $img=new Imagick(); 
  220.                     $img->readImageBlob($frame); 
  221.                     $img->cropImage($crop_w,$crop_h,$crop_x,$crop_y); 
  222.                     $img->thumbnailImage($width,$height,true); 
  223.                     $canvas->addImage($img); 
  224.                     $canvas->setImageDelay($img->getImageDelay()); 
  225.                     $canvas->setImagePage($width,$height,0,0); 
  226.                 } 
  227.             }else
  228.                 $image->cropImage($crop_w,$crop_h,$crop_x,$crop_y); 
  229.                 $image->thumbnailImage($width,$height,true); 
  230.                 $canvas->addImage($image); 
  231.                 $canvas->setImagePage($width,$height,0,0); 
  232.             } 
  233.             $image->destroy(); 
  234.             $this->image=$canvas
  235.         } 
  236.     } 
  237.     /** 
  238.         添加图片水印 
  239.         参数: 
  240.             $path:水印图片(包含完整路径) 
  241.             $x,$y:水印座标 
  242.     /**/ 
  243.     public function add_watermark($path,$x=0,$y=0){ 
  244.         $watermark=new Imagick($path); 
  245.         $draw=new ImagickDraw(); 
  246.         $draw->composite($watermark->getImageCompose(),$x,$y,$watermark->getImageWidth(),$watermark->getimageheight(),$watermark); 
  247.         if($this->type=='gif'){ 
  248.             $image=$this->image; 
  249.             $canvas=new Imagick(); 
  250.             $images=$image->coalesceImages(); 
  251.             foreach($image as $frame){ 
  252.                 $img=new Imagick(); 
  253.                 $img->readImageBlob($frame); 
  254.                 $img->drawImage($draw); 
  255.                 $canvas->addImage($img); 
  256.                 $canvas->setImageDelay($img->getImageDelay()); 
  257.             } 
  258.             $image->destroy(); 
  259.             $this->image=$canvas
  260.         }else
  261.             $this->image->drawImage($draw); 
  262.         } 
  263.     } 
  264.     /** 
  265.         添加文字水印 
  266.         参数: 
  267.             $text:水印文字 
  268.             $x,$y:水印座标 
  269.     /**/ 
  270.     public function add_text($text,$x=0,$y=0,$angle=0,$style=array()){ 
  271.         $draw=new ImagickDraw(); 
  272.         if(isset($style['font'])) $draw->setFont($style['font']); 
  273.         if(isset($style['font_size'])) $draw->setFontSize($style['font_size']); 
  274.         if(isset($style['fill_color'])) $draw->setFillColor($style['fill_color']); 
  275.         if(isset($style['under_color'])) $draw->setTextUnderColor($style['under_color']); 
  276.         if($this->type=='gif'){ 
  277.             foreach($this->image as $frame){ 
  278.                 $frame->annotateImage($draw,$x,$y,$angle,$text); 
  279.             } 
  280.         }else
  281.             $this->image->annotateImage($draw,$x,$y,$angle,$text); 
  282.         } 
  283.     } 
  284.     /** 
  285.         图片存档 
  286.         参数: 
  287.             $path:存档的位置和新的档案名 
  288.     /**/ 
  289.     public function save_to($path){ 
  290.         $this->image->stripImage(); 
  291.         switch($this->type){ 
  292.         case 'gif'
  293.             $this->image->writeImages($path,true); 
  294.             return ; 
  295.         case 'jpg'
  296.         case 'jpeg'
  297.             $this->image->setImageCompressionQuality($_ENV['ImgQ']); 
  298.             $this->image->writeImage($path); 
  299.             return ; 
  300.         case 'png'
  301.             $flag = $this->image->getImageAlphaChannel(); 
  302.             // 如果png背景不透明则压缩 
  303.             if(imagick::ALPHACHANNEL_UNDEFINED == $flag or imagick::ALPHACHANNEL_DEACTIVATE == $flag){ 
  304.                 $this->image->setImageType(imagick::IMGTYPE_PALETTE); 
  305.                 $this->image->writeImage($path); 
  306.             }else
  307.                 $this->image->writeImage($path); 
  308.             }unset($flag); 
  309.             return ; 
  310.         default
  311.             $this->image->writeImage($path); 
  312.             return ; 
  313.         } 
  314.     } 
  315.     // 直接输出图像到萤幕 
  316.     public function output($header=true){ 
  317.         if($header) header('Content-type: '.$this->type); 
  318.         echo $this->image->getImagesBlob(); 
  319.     } 
  320.     /** 
  321.         建立缩小图 
  322.         $fit为真时,将保持比例并在$width X $height内產生缩小图 
  323.     /**/ 
  324.     public function thumbnail($width=100,$height=100,$fit=true){$this->image->thumbnailImage($width,$height,$fit);} 
  325.     /** 
  326.         给图像添加边框 
  327.         $width: 左右边框宽度 
  328.         $height: 上下边框宽度 
  329.         $color: 顏色 
  330.     /**/ 
  331.     public function border($width,$height,$color='rgb(220,220,220)'){ 
  332.         $color=new ImagickPixel(); 
  333.         $color->setColor($color); 
  334.         $this->image->borderImage($color,$width,$height); 
  335.     } 
  336.     //取得图像宽度 
  337.     public function get_width(){$size=$this->image->getImagePage();return $size['width'];} 
  338.     //取得图像高度 
  339.     public function get_height(){$size=$this->image->getImagePage();return $size['height'];} 
  340.     // 设置图像类型 
  341.     public function set_type($type='png'){$this->type=$type;$this->image->setImageFormat($type);} 
  342.     // 取得图像类型 
  343.     public function get_type(){return $this->type;} 
  344.     public function blur($radius,$sigma){$this->image->blurImage($radius,$sigma);} // 模糊 
  345.     public function gaussian_blur($radius,$sigma){$this->image->gaussianBlurImage($radius,$sigma);} // 高斯模糊 
  346.     public function motion_blur($radius,$sigma,$angle){$this->image->motionBlurImage($radius,$sigma,$angle);} // 运动模糊 
  347.     public function radial_blur($radius){$this->image->radialBlurImage($radius);} // 径向模糊 
  348.     public function add_noise($type=null){$this->image->addNoiseImage($type==null?imagick::NOISE_IMPULSE:$type);} // 添加噪点 
  349.     public function level($black_point,$gamma,$white_point){$this->image->levelImage($black_point,$gamma,$white_point);} // 调整色阶 
  350.     public function modulate($brightness,$saturation,$hue){$this->image->modulateImage($brightness,$saturation,$hue);} // 调整亮度,饱和度,色调 
  351.     public function charcoal($radius,$sigma){$this->image->charcoalImage($radius,$sigma);} // 素描效果 
  352.     public function oil_paint($radius){$this->image->oilPaintImage($radius);} // 油画效果 
  353.     public function flop(){$this->image->flopImage();} // 水平翻转 
  354.     public function flip(){$this->image->flipImage();} // 垂直翻转 

状况二的解决办法如下:

首先用/usr/local/imagemagick/bin/convert -version指令查看一下输出内容是否已经开啟了多线程,Features:的值为空说明是单线程,如果Features:的值是openMP说明是多线程.imagick的多线程模式有一个bug,他会导致多核心的cpu使用率瞬间飆升到100所以一定要使用它的单线程模式才行.

Version: ImageMagick 6.7.1-2 2014-05-29 Q16 http://www.imagemagick.org

Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC

Features: 

上边是我配置正确时显示的结果,如果没有配置正确会显示下边的结果,代码如下:

Version: ImageMagick 6.7.1-2 2014-05-29 Q16 http://www.imagemagick.org

Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC

Features: openMP

第一种结果是单线程模式,第二种结果是多线程模式,因为imagick的多线程模式有bug,所以如果您刚开始是用多线程模式安装的imagick那就必须要yum remove imagemagick将其卸载掉重新安装才行.

经过重写class,重装imagick之后一切正常,而且处理图像的效能比之以前有了大幅提升

Tags: php扩展 imagick

分享到: