關於imagick不得不說的一些事

    PHP建圖通常都用GD庫,因為是內置的不需要在服務器上額外安裝插件,所以用起來比較省心,但是如果你的程序主要的功能就是處理圖像,那麼就不建議用GD了,因為GD不但低效能而且能力也比較弱,佔用的系統資源也頗多,另外GD的creatfrom???也有bug,而imagick卻是一個很好的替代品,為此最近把我的一個項目由GD改成了imagick,但是改完之後出現了一些狀況在此分享給大家.

    首先說一下我這邊出現的狀況:

    狀況一:需要重寫圖像操作class

    狀況二:imagick多線程時會導致cpu使用率暴增到100%

    在此順便提一下imagick在centos6.4的安裝方法:

	1、安装ImageMagick

	wget http://soft.vpser.net/web/imagemagick/ImageMagick-6.7.1-2.tar.gz

	tar zxvf ImageMagick-6.7.1-2.tar.gz

	cd ImageMagick-6.7.1-2/

	./configure --prefix=/usr/local/imagemagick --disable-openmp

	make && make install

	ldconfig



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

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



	2、安装PHP扩展:imagick

	wget http://pecl.php.net/get/imagick-3.0.1.tgz

	tar zxvf imagick-3.0.1.tgz

	cd imagick-3.0.1/

	/usr/local/php/bin/phpize

	./configure --with-php-config=/usr/local/php/bin/php-config --with-imagick=/usr/local/imagemagick

	make && make install

	ldconfig

	vi /usr/local/php/etc/php.ini

	添加:extension = "imagick.so"



	重启lnmp

	/root/lnmp reload

 

    接下來我們針對上述兩個狀況分別提出解決辦法:

狀況一的解決辦法如下:

關於imagick不得不說的一些事
  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 

 15 define('CLASS_IMAGICK',TRUE);

 16 class class_imagick{

 17     private $image=null;

 18     private $type=null;

 19 

 20     // 構造

 21     public function __construct(){}

 22 

 23     // 析構

 24     public function __destruct(){

 25         if($this->image!==null){$this->image->destroy();}

 26     }

 27 

 28     // 載入圖像

 29     public function open($path){

 30         if(!file_exists($path)){

 31             $this->image=null;

 32             return ;

 33         }

 34         $this->image=new Imagick($path);

 35         if($this->image){

 36             $this->type=strtolower($this->image->getImageFormat());

 37         }

 38         $this->image->stripImage();

 39         return $this->image;

 40     }

 41 

 42     /**

 43         圖像裁切

 44     /**/

 45     public function crop($x=0,$y=0,$width=null,$height=null){

 46         if($width==null) $width=$this->image->getImageWidth()-$x;

 47         if($height==null) $height=$this->image->getImageHeight()-$y;

 48         if($width<=0 || $height<=0) return;

 49 

 50         if($this->type=='gif'){

 51             $image=$this->image;

 52             $canvas=new Imagick();

 53 

 54             $images=$image->coalesceImages();

 55             foreach($images as $frame){

 56                 $img=new Imagick();

 57                 $img->readImageBlob($frame);

 58                 $img->cropImage($width,$height,$x,$y);

 59 

 60                 $canvas->addImage($img);

 61                 $canvas->setImageDelay($img->getImageDelay());

 62                 $canvas->setImagePage($width,$height,0,0);

 63             }

 64 

 65             $image->destroy();

 66             $this->image=$canvas;

 67         }else{

 68             $this->image->cropImage($width,$height,$x,$y);

 69         }

 70     }

 71 

 72     /**

 73         更改圖像大小

 74         參數:

 75             $width:新的寬度

 76             $height:新的高度

 77             $fit: 適應大小

 78                 'force': 把圖像強制改為$width X $height

 79                 'scale': 按比例在$width X $height內縮放圖片,結果不完全等於$width X $height

 80                 'scale_fill':按比例在$width X $height內縮放圖片,沒有像素的地方填充顏色$fill_color=array(255,255,255)(红,绿,蓝,透明度[0不透明-127全透明])

 81                 其他:智能模式,縮放圖片並從正中裁切$width X $height的大小

 82         注意:

 83             $fit='force','scale','scale_fill'時輸出完整圖像

 84             $fit=圖像方位時輸出指定位置部份的圖像

 85         字母與圖像的對應關係如下:

 86             north_west   north   north_east

 87             west         center        east

 88             south_west   south   south_east

 89     /**/

 90     public function resize_to($width=100,$height=100,$fit='center',$fill_color=array(255,255,255,0)){

 91         switch($fit){

 92         case 'force':

 93             if($this->type=='gif'){

 94                 $image=$this->image;

 95                 $canvas=new Imagick();

 96 

 97                 $images=$image->coalesceImages();

 98                 foreach($images as $frame){

 99                     $img=new Imagick();

100                     $img->readImageBlob($frame);

101                     $img->thumbnailImage($width,$height,false);

102 

103                     $canvas->addImage($img);

104                     $canvas->setImageDelay($img->getImageDelay());

105                 }

106                 $image->destroy();

107                 $this->image=$canvas;

108             }else{

109                 $this->image->thumbnailImage($width,$height,false);

110             }

111             break;

112         case 'scale':

113             if($this->type=='gif'){

114                 $image=$this->image;

115                 $images=$image->coalesceImages();

116                 $canvas=new Imagick();

117                 foreach($images as $frame){

118                     $img=new Imagick();

119                     $img->readImageBlob($frame);

120                     $img->thumbnailImage($width,$height,true);

121 

122                     $canvas->addImage($img);

123                     $canvas->setImageDelay($img->getImageDelay());

124                 }

125                 $image->destroy();

126                 $this->image=$canvas;

127             }else{

128                 $this->image->thumbnailImage($width,$height,true);

129             }

130             break;

131         case 'scale_fill':

132             $size=$this->image->getImagePage();

133             $src_width=$size['width'];

134             $src_height=$size['height'];

135 

136             $x=0;

137             $y=0;

138 

139             $dst_width=$width;

140             $dst_height=$height;

141 

142             if($src_width*$height > $src_height*$width){

143                 $dst_height=intval($width*$src_height/$src_width);

144                 $y=intval(($height-$dst_height)/2);

145             }else{

146                 $dst_width=intval($height*$src_width/$src_height);

147                 $x=intval(($width-$dst_width)/2);

148             }

149 

150             $image=$this->image;

151             $canvas=new Imagick();

152 

153             $color='rgba('.$fill_color[0].','.$fill_color[1].','.$fill_color[2].','.$fill_color[3].')';

154             if($this->type=='gif'){

155                 $images=$image->coalesceImages();

156                 foreach($images as $frame){

157                     $frame->thumbnailImage($width,$height,true);

158 

159                     $draw=new ImagickDraw();

160                     $draw->composite($frame->getImageCompose(),$x,$y,$dst_width,$dst_height,$frame);

161 

162                     $img=new Imagick();

163                     $img->newImage($width,$height,$color,'gif');

164                     $img->drawImage($draw);

165 

166                     $canvas->addImage($img);

167                     $canvas->setImageDelay($img->getImageDelay());

168                     $canvas->setImagePage($width,$height,0,0);

169                 }

170             }else{

171                 $image->thumbnailImage($width,$height,true);

172 

173                 $draw=new ImagickDraw();

174                 $draw->composite($image->getImageCompose(),$x,$y,$dst_width,$dst_height,$image);

175 

176                 $canvas->newImage($width,$height,$color,$this->get_type());

177                 $canvas->drawImage($draw);

178                 $canvas->setImagePage($width,$height,0,0);

179             }

180             $image->destroy();

181             $this->image=$canvas;

182             break;

183         default:

184             $size=$this->image->getImagePage();

185             $src_width=$size['width'];

186             $src_height=$size['height'];

187 

188             $crop_x=0;

189             $crop_y=0;

190 

191             $crop_w=$src_width;

192             $crop_h=$src_height;

193 

194             if($src_width*$height > $src_height*$width){

195                 $crop_w=intval($src_height*$width/$height);

196             }else{

197                 $crop_h=intval($src_width*$height/$width);

198             }

199 

200             switch($fit){

201                 case 'north_west':

202                     $crop_x=0;

203                     $crop_y=0;

204                     break;

205                 case 'north':

206                     $crop_x=intval(($src_width-$crop_w)/2);

207                     $crop_y=0;

208                     break;

209                 case 'north_east':

210                     $crop_x=$src_width-$crop_w;

211                     $crop_y=0;

212                     break;

213                 case 'west':

214                     $crop_x=0;

215                     $crop_y=intval(($src_height-$crop_h)/2);

216                     break;

217                 case 'center':

218                     $crop_x=intval(($src_width-$crop_w)/2);

219                     $crop_y=intval(($src_height-$crop_h)/2);

220                     break;

221                 case 'east':

222                     $crop_x=$src_width-$crop_w;

223                     $crop_y=intval(($src_height-$crop_h)/2);

224                     break;

225                 case 'south_west':

226                     $crop_x=0;

227                     $crop_y=$src_height-$crop_h;

228                     break;

229                 case 'south':

230                     $crop_x=intval(($src_width-$crop_w)/2);

231                     $crop_y=$src_height-$crop_h;

232                     break;

233                 case 'south_east':

234                     $crop_x=$src_width-$crop_w;

235                     $crop_y=$src_height-$crop_h;

236                     break;

237                 default:

238                     $crop_x=intval(($src_width-$crop_w)/2);

239                     $crop_y=intval(($src_height-$crop_h)/2);

240             }

241 

242             $image=$this->image;

243             $canvas=new Imagick();

244 

245             if($this->type=='gif'){

246                 $images=$image->coalesceImages();

247                 foreach($images as $frame){

248                     $img=new Imagick();

249                     $img->readImageBlob($frame);

250                     $img->cropImage($crop_w,$crop_h,$crop_x,$crop_y);

251                     $img->thumbnailImage($width,$height,true);

252 

253                     $canvas->addImage($img);

254                     $canvas->setImageDelay($img->getImageDelay());

255                     $canvas->setImagePage($width,$height,0,0);

256                 }

257             }else{

258                 $image->cropImage($crop_w,$crop_h,$crop_x,$crop_y);

259                 $image->thumbnailImage($width,$height,true);

260                 $canvas->addImage($image);

261                 $canvas->setImagePage($width,$height,0,0);

262             }

263             $image->destroy();

264             $this->image=$canvas;

265         }

266     }

267 

268     /**

269         添加圖片水印

270         參數:

271             $path:水印圖片(包含完整路徑)

272             $x,$y:水印座標

273     /**/

274     public function add_watermark($path,$x=0,$y=0){

275         $watermark=new Imagick($path);

276         $draw=new ImagickDraw();

277         $draw->composite($watermark->getImageCompose(),$x,$y,$watermark->getImageWidth(),$watermark->getimageheight(),$watermark);

278 

279         if($this->type=='gif'){

280             $image=$this->image;

281             $canvas=new Imagick();

282             $images=$image->coalesceImages();

283             foreach($image as $frame){

284                 $img=new Imagick();

285                 $img->readImageBlob($frame);

286                 $img->drawImage($draw);

287 

288                 $canvas->addImage($img);

289                 $canvas->setImageDelay($img->getImageDelay());

290             }

291             $image->destroy();

292             $this->image=$canvas;

293         }else{

294             $this->image->drawImage($draw);

295         }

296     }

297 

298     /**

299         添加文字水印

300         參數:

301             $text:水印文字

302             $x,$y:水印座標

303     /**/

304     public function add_text($text,$x=0,$y=0,$angle=0,$style=array()){

305         $draw=new ImagickDraw();

306         if(isset($style['font'])) $draw->setFont($style['font']);

307         if(isset($style['font_size'])) $draw->setFontSize($style['font_size']);

308         if(isset($style['fill_color'])) $draw->setFillColor($style['fill_color']);

309         if(isset($style['under_color'])) $draw->setTextUnderColor($style['under_color']);

310 

311         if($this->type=='gif'){

312             foreach($this->image as $frame){

313                 $frame->annotateImage($draw,$x,$y,$angle,$text);

314             }

315         }else{

316             $this->image->annotateImage($draw,$x,$y,$angle,$text);

317         }

318     }

319 

320     /**

321         圖片存檔

322         參數:

323             $path:存檔的位置和新的檔案名

324     /**/

325     public function save_to($path){

326         $this->image->stripImage();

327         switch($this->type){

328         case 'gif':

329             $this->image->writeImages($path,true);

330             return ;

331         case 'jpg':

332         case 'jpeg':

333             $this->image->setImageCompressionQuality($_ENV['ImgQ']);

334             $this->image->writeImage($path);

335             return ;

336         case 'png':

337             $flag = $this->image->getImageAlphaChannel();

338 

339             // 如果png背景不透明則壓縮

340             if(imagick::ALPHACHANNEL_UNDEFINED == $flag or imagick::ALPHACHANNEL_DEACTIVATE == $flag){

341                 $this->image->setImageType(imagick::IMGTYPE_PALETTE);

342                 $this->image->writeImage($path);

343             }else{

344                 $this->image->writeImage($path);

345             }unset($flag);

346             return ;

347         default:

348             $this->image->writeImage($path);

349             return ;

350         }

351     }

352 

353     // 直接輸出圖像到螢幕

354     public function output($header=true){

355         if($header) header('Content-type: '.$this->type);

356         echo $this->image->getImagesBlob();

357     }

358 

359     /**

360         建立縮小圖

361         $fit為真時,將保持比例並在$width X $height内產生縮小圖

362     /**/

363     public function thumbnail($width=100,$height=100,$fit=true){$this->image->thumbnailImage($width,$height,$fit);}

364 

365     /**

366         給圖像添加邊框

367         $width: 左右邊框寬度

368         $height: 上下邊框寬度

369         $color: 顏色

370     /**/

371     public function border($width,$height,$color='rgb(220,220,220)'){

372         $color=new ImagickPixel();

373         $color->setColor($color);

374         $this->image->borderImage($color,$width,$height);

375     }

376 

377     //取得圖像寬度

378     public function get_width(){$size=$this->image->getImagePage();return $size['width'];}

379 

380     //取得圖像高度

381     public function get_height(){$size=$this->image->getImagePage();return $size['height'];}

382 

383     // 設置圖像類型

384     public function set_type($type='png'){$this->type=$type;$this->image->setImageFormat($type);}

385 

386     // 取得圖像類型

387     public function get_type(){return $this->type;}

388 

389     public function blur($radius,$sigma){$this->image->blurImage($radius,$sigma);} // 模糊

390     public function gaussian_blur($radius,$sigma){$this->image->gaussianBlurImage($radius,$sigma);} // 高斯模糊

391     public function motion_blur($radius,$sigma,$angle){$this->image->motionBlurImage($radius,$sigma,$angle);} // 運動模糊

392     public function radial_blur($radius){$this->image->radialBlurImage($radius);} // 徑向模糊

393     public function add_noise($type=null){$this->image->addNoiseImage($type==null?imagick::NOISE_IMPULSE:$type);} // 添加噪點

394     public function level($black_point,$gamma,$white_point){$this->image->levelImage($black_point,$gamma,$white_point);} // 調整色階

395     public function modulate($brightness,$saturation,$hue){$this->image->modulateImage($brightness,$saturation,$hue);} // 調整亮度,飽和度,色調

396     public function charcoal($radius,$sigma){$this->image->charcoalImage($radius,$sigma);} // 素描效果

397     public function oil_paint($radius){$this->image->oilPaintImage($radius);} // 油畫效果

398     public function flop(){$this->image->flopImage();} // 水平翻轉

399     public function flip(){$this->image->flipImage();} // 垂直翻轉

400 }
View Code

狀況二的解決辦法如下:

首先用/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之後一切正常,而且處理圖像的效能比之以前有了大幅提升

 

 

 

 

你可能感兴趣的:(IM)