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
登录后复制
接下來我們針對上述兩個狀況分別提出解決辦法:
狀況一的解決辦法如下:
![](http://www.bkjia.com/uploads/allimg/140530/121Q33536-0.gif)
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之後一切正常,而且處理圖像的效能比之以前有了大幅提升
http://www.bkjia.com/PHPjc/778220.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/778220.htmlTechArticlePHP建圖通常都用GD庫,因為是內置的不需要在服務器上額外安裝插件,所以用起來比較省心,但是如果你的程序主要的功能就是處理圖像,那麼就...