The GD library is usually used for PHP mapping. Because it is built-in and does not require additional plug-ins to be installed on the server, it is more worry-free to use. However, if the main function of your program is to process images, then it is not necessary. It is recommended to use GD, because GD is not only inefficient but also relatively weak, and it takes up a lot of system resources. In addition, GD's creatfrom??? also has bugs, but imagick is a good alternative. For this reason, I recently One of my projects was changed from GD to imagick, but after the change, some situations occurred and I would like to share them with you here.
First let me talk about the situation here:
Situation 1: Image operation class needs to be rewritten
Situation 2: Multi-threading of imagick will cause the CPU usage to surge to 100%
By the way, here’s how to install imagick on 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
Copy after login
Next we propose solutions to the above two situations:
The solution to situation 1 is as follows:
![](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 Change image size
74 Parameters:
75 $width: new width
76 $height: new height
77 $fit: fit to size
78 'force': Force the image to $width X $height
79 'scale': scale the image proportionally within $width X $height, the result is not exactly equal to $width X $height
80 'scale_fill': scale the image proportionally within $width [0 opaque-127 fully transparent])
81 Others: Smart mode, scale the image and crop it from the center to the size of $width X $height
82 Note:
83 Output the complete image when $fit='force','scale','scale_fill'
84 $fit=Outputs the image at the specified position when the image is oriented.
85 The corresponding relationship between letters and images is as follows:
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 Add text watermark
300 Parameters:
301 $text: watermark text
302 $x, $y: watermark coordinates
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 Picture archive
322 Parameters:
323 $path: Archive location and new file name
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 // Compress png if background is opaque
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 // Directly output the image to the screen
354 public function output(
$header=
true){
355 if(
$header)
header('Content-type: '.
$this ->
type);
356 echo $this->image->
getImagesBlob();
357 }
358
359 /**
360 Create a thumbnail
361 When $fit is true, the proportion will be maintained and a reduced image will be generated within $width X $height
362 /**/
363 public function thumbnail(
$width=100,
$height=100,
$fit =
true){
$this->image->thumbnailImage(
$width,
$height,
$fit);}
364
365 /**
366 Add borders to images
367 $width: left and right border width
368 $height: top and bottom border width
369 $color: 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 //Get image width
378 public function get_width(){
$size=
$this->image->getImagePage ();
return $size['width'
];}
379
380 //Get the image height
381 public function get_height(){
$size=
$this->image->getImagePage ();
return $size['height'
];}
382
383 // Set image type
384 public function set_type(
$type='png'){
$this->type=
$type;
$this->image->setImageFormat(
$type);}
385
386 // Get image type
387 public function get_type(){
return $this->
type;}
388
389 public function blur(
$radius,
$sigma){
$this ->image->blurImage(
$radius,
$sigma);}
// Blur
390 public function gaussian_blur(
$radius,
$sigma){
$this ->image->gaussianBlurImage(
$radius,
$sigma);}
// Gaussian Blur
391 public function motion_blur(
$radius,
$sigma,
$angle) {
$this->image->motionBlurImage(
$radius,
$sigma,
$angle);}
// Motion blur
392 public function radial_blur(
$radius){
$this->image->radialBlurImage(
$radius);}
// Radial blur
393 public function add_noise(
$type=
null){
$this- >image->addNoiseImage(
$type==
null?imagick::NOISE_IMPULSE:
$type);}
// Add noise
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:
Copy after login
上邊是我配置正確時顯示的結果,如果沒有配置正確會顯示下邊的結果
Version: ImageMagick 6.7.1-2 2014-05-29 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
Features: openMP
Copy after login
第一種結果是單線程模式,第二種結果是多線程模式,因為imagick的多線程模式有bug,所以如果您剛開始是用多線程模式安裝的imagick那就必須要yum remove imagemagick將其卸載掉重新安裝才行.
經過重寫class,重裝imagick之後一切正常,而且處理圖像的效能比之以前有了大幅提升
http://www.bkjia.com/PHPjc/778220.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/778220.htmlTechArticlePHP建圖通常都用GD庫,因為是內置的不需要在服務器上額外安裝插件,所以用起來比較省心,但是如果你的程序主要的功能就是處理圖像,那麼就...