php扩展imagick的说明和实例,如:添加水印、图片剪裁、图片大小等 ImageMagick

分类:PHP_Python| 发布:佚名| 查看:565 | 发表时间:2014/11/30

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

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

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

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

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

1、安装ImageMagick

代码如下:
001wget upload/2014/11/201411141106431410.gif');
002        $Imagick->resize_to(100,100,'scale_fill');
003        $Imagick->add_text('1024i.com',10,20);
004        $Imagick->add_watermark('1024i.gif',10,50);
005        $Imagick->save_to('x.gif');
006        unset($Imagick);
007/**/
008define('CLASS_IMAGICK',TRUE);
009class class_imagick{
010    private $image=null;
011    private $type=null;
012    // 构造
013    public function __construct(){}
014    // 析构
015    public function __destruct(){
016        if($this->image!==null){$this->image->destroy();}
017    }
018    // 载入图像
019    public function open($path){
020        if(!file_exists($path)){
021            $this->image=null;
022            return ;
023        }
024        $this->image=new Imagick($path);
025        if($this->image){
026            $this->type=strtolower($this->image->getImageFormat());
027        }
028        $this->image->stripImage();
029        return $this->image;
030    }
031    /**
032        图像裁切
033    /**/
034    public function crop($x=0,$y=0,$width=null,$height=null){
035        if($width==null) $width=$this->image->getImageWidth()-$x;
036        if($height==null) $height=$this->image->getImageHeight()-$y;
037        if($width<=0 || $height<=0) return;
038        if($this->type=='gif'){
039            $image=$this->image;
040            $canvas=new Imagick();
041            $images=$image->coalesceImages();
042            foreach($images as $frame){
043                $img=new Imagick();
044                $img->readImageBlob($frame);
045                $img->cropImage($width,$height,$x,$y);
046                $canvas->addImage($img);
047                $canvas->setImageDelay($img->getImageDelay());
048                $canvas->setImagePage($width,$height,0,0);
049            }
050            $image->destroy();
051            $this->image=$canvas;
052        }else{
053            $this->image->cropImage($width,$height,$x,$y);
054        }
055    }
056    /**
057        更改图像大小 @郑州网建
058        参数:
059            $width:新的宽度
060            $height:新的高度
061            $fit: 适应大小
062                'force': 把图像强制改为$width X $height
063                'scale': 按比例在$width X $height内缩放图片,结果不完全等於$width X $height
064                'scale_fill':按比例在$width X $height内缩放图片,没有像素的地方填充顏色$fill_color=array(255,255,255)(红,绿,蓝,透明度[0不透明-127全透明])
065                其他:智能模式,缩放图片并从正中裁切$width X $height的大小
066        注意:
067            $fit='force','scale','scale_fill'时输出完整图像
068            $fit=图像方位时输出指定位置部份的图像
069        字母与图像的对应关系如下:
070            north_west   north   north_east
071            west         center        east
072            south_west   south   south_east
073    /**/
074    public function resize_to($width=100,$height=100,$fit='center',$fill_color=array(255,255,255,0)){
075        switch($fit){
076        case 'force':
077            if($this->type=='gif'){
078                $image=$this->image;
079                $canvas=new Imagick();
080                $images=$image->coalesceImages();
081                foreach($images as $frame){
082                    $img=new Imagick();
083                    $img->readImageBlob($frame);
084                    $img->thumbnailImage($width,$height,false);
085                    $canvas->addImage($img);
086                    $canvas->setImageDelay($img->getImageDelay());
087                }
088                $image->destroy();
089                $this->image=$canvas;
090            }else{
091                $this->image->thumbnailImage($width,$height,false);
092            }
093            break;
094        case 'scale':
095            if($this->type=='gif'){
096                $image=$this->image;
097                $images=$image->coalesceImages();
098                $canvas=new Imagick();
099                foreach($images as $frame){
100                    $img=new Imagick();
101                    $img->readImageBlob($frame);
102                    $img->thumbnailImage($width,$height,true);
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,true);
110            }
111            break;
112        case 'scale_fill':
113            $size=$this->image->getImagePage();
114            $src_width=$size['width'];
115            $src_height=$size['height'];
116            $x=0;
117            $y=0;
118            $dst_width=$width;
119            $dst_height=$height;
120            if($src_width*$height > $src_height*$width){
121                $dst_height=intval($width*$src_height/$src_width);
122                $y=intval(($height-$dst_height)/2);
123            }else{
124                $dst_width=intval($height*$src_width/$src_height);
125                $x=intval(($width-$dst_width)/2);
126            }
127            $image=$this->image;
128            $canvas=new Imagick();
129            $color='rgba('.$fill_color[0].','.$fill_color[1].','.$fill_color[2].','.$fill_color[3].')';
130            if($this->type=='gif'){
131                $images=$image->coalesceImages();
132                foreach($images as $frame){
133                    $frame->thumbnailImage($width,$height,true);
134                    $draw=new ImagickDraw();
135                    $draw->composite($frame->getImageCompose(),$x,$y,$dst_width,$dst_height,$frame);
136                    $img=new Imagick();
137                    $img->newImage($width,$height,$color,'gif');
138                    $img->drawImage($draw);
139                    $canvas->addImage($img);
140                    $canvas->setImageDelay($img->getImageDelay());
141                    $canvas->setImagePage($width,$height,0,0);
142                }
143            }else{
144                $image->thumbnailImage($width,$height,true);
145                $draw=new ImagickDraw();
146                $draw->composite($image->getImageCompose(),$x,$y,$dst_width,$dst_height,$image);
147                $canvas->newImage($width,$height,$color,$this->get_type());
148                $canvas->drawImage($draw);
149                $canvas->setImagePage($width,$height,0,0);
150            }
151            $image->destroy();
152            $this->image=$canvas;
153            break;
154        default:
155            $size=$this->image->getImagePage();
156            $src_width=$size['width'];
157            $src_height=$size['height'];
158            $crop_x=0;
159            $crop_y=0;
160            $crop_w=$src_width;
161            $crop_h=$src_height;
162            if($src_width*$height > $src_height*$width){
163                $crop_w=intval($src_height*$width/$height);
164            }else{
165                $crop_h=intval($src_width*$height/$width);
166            }
167            switch($fit){
168                case 'north_west':
169                    $crop_x=0;
170                    $crop_y=0;
171                    break;
172                case 'north':
173                    $crop_x=intval(($src_width-$crop_w)/2);
174                    $crop_y=0;
175                    break;
176                case 'north_east':
177                    $crop_x=$src_width-$crop_w;
178                    $crop_y=0;
179                    break;
180                case 'west':
181                    $crop_x=0;
182                    $crop_y=intval(($src_height-$crop_h)/2);
183                    break;
184                case 'center':
185                    $crop_x=intval(($src_width-$crop_w)/2);
186                    $crop_y=intval(($src_height-$crop_h)/2);
187                    break;
188                case 'east':
189                    $crop_x=$src_width-$crop_w;
190                    $crop_y=intval(($src_height-$crop_h)/2);
191                    break;
192                case 'south_west':
193                    $crop_x=0;
194                    $crop_y=$src_height-$crop_h;
195                    break;
196                case 'south':
197                    $crop_x=intval(($src_width-$crop_w)/2);
198                    $crop_y=$src_height-$crop_h;
199                    break;
200                case 'south_east':
201                    $crop_x=$src_width-$crop_w;
202                    $crop_y=$src_height-$crop_h;
203                    break;
204                default:
205                    $crop_x=intval(($src_width-$crop_w)/2);
206                    $crop_y=intval(($src_height-$crop_h)/2);
207            }
208            $image=$this->image;
209            $canvas=new Imagick();
210            if($this->type=='gif'){
211                $images=$image->coalesceImages();
212                foreach($images as $frame){
213                    $img=new Imagick();
214                    $img->readImageBlob($frame);
215                    $img->cropImage($crop_w,$crop_h,$crop_x,$crop_y);
216                    $img->thumbnailImage($width,$height,true);
217                    $canvas->addImage($img);
218                    $canvas->setImageDelay($img->getImageDelay());
219                    $canvas->setImagePage($width,$height,0,0);
220                }
221            }else{
222                $image->cropImage($crop_w,$crop_h,$crop_x,$crop_y);
223                $image->thumbnailImage($width,$height,true);
224                $canvas->addImage($image);
225                $canvas->setImagePage($width,$height,0,0);
226            }
227            $image->destroy();
228            $this->image=$canvas;
229        }
230    }
231    /**
232        添加图片水印
233        参数:
234            $path:水印图片(包含完整路径)
235            $x,$y:水印座标
236    /**/
237    public function add_watermark($path,$x=0,$y=0){
238        $watermark=new Imagick($path);
239        $draw=new ImagickDraw();
240        $draw->composite($watermark->getImageCompose(),$x,$y,$watermark->getImageWidth(),$watermark->getimageheight(),$watermark);
241        if($this->type=='gif'){
242            $image=$this->image;
243            $canvas=new Imagick();
244            $images=$image->coalesceImages();
245            foreach($image as $frame){
246                $img=new Imagick();
247                $img->readImageBlob($frame);
248                $img->drawImage($draw);
249                $canvas->addImage($img);
250                $canvas->setImageDelay($img->getImageDelay());
251            }
252            $image->destroy();
253            $this->image=$canvas;
254        }else{
255            $this->image->drawImage($draw);
256        }
257    }
258    /**
259        添加文字水印
260        参数:
261            $text:水印文字
262            $x,$y:水印座标
263    /**/
264    public function add_text($text,$x=0,$y=0,$angle=0,$style=array()){
265        $draw=new ImagickDraw();
266        if(isset($style['font'])) $draw->setFont($style['font']);
267        if(isset($style['font_size'])) $draw->setFontSize($style['font_size']);
268        if(isset($style['fill_color'])) $draw->setFillColor($style['fill_color']);
269        if(isset($style['under_color'])) $draw->setTextUnderColor($style['under_color']);
270        if($this->type=='gif'){
271            foreach($this->image as $frame){
272                $frame->annotateImage($draw,$x,$y,$angle,$text);
273            }
274        }else{
275            $this->image->annotateImage($draw,$x,$y,$angle,$text);
276        }
277    }
278    /**
279        图片存档
280        参数:
281            $path:存档的位置和新的档案名
282    /**/
283    public function save_to($path){
284        $this->image->stripImage();
285        switch($this->type){
286        case 'gif':
287            $this->image->writeImages($path,true);
288            return ;
289        case 'jpg':
290        case 'jpeg':
291            $this->image->setImageCompressionQuality($_ENV['ImgQ']);
292            $this->image->writeImage($path);
293            return ;
294        case 'png':
295            $flag = $this->image->getImageAlphaChannel();
296            // 如果png背景不透明则压缩
297            if(imagick::ALPHACHANNEL_UNDEFINED == $flag or imagick::ALPHACHANNEL_DEACTIVATE == $flag){
298                $this->image->setImageType(imagick::IMGTYPE_PALETTE);
299                $this->image->writeImage($path);
300            }else{
301                $this->image->writeImage($path);
302            }unset($flag);
303            return ;
304        default:
305            $this->image->writeImage($path);
306            return ;
307        }
308    }
309    // 直接输出图像到萤幕
310    public function output($header=true){
311        if($header) header('Content-type: '.$this->type);
312        echo $this->image->getImagesBlob();
313    }
314    /**
315        建立缩小图
316        $fit为真时,将保持比例并在$width X $height内產生缩小图
317    /**/
318    public function thumbnail($width=100,$height=100,$fit=true){$this->image->thumbnailImage($width,$height,$fit);}
319    /**
320        给图像添加边框
321        $width: 左右边框宽度
322        $height: 上下边框宽度
323        $color: 顏色
324    /**/
325    public function border($width,$height,$color='rgb(220,220,220)'){
326        $color=new ImagickPixel();
327        $color->setColor($color);
328        $this->image->borderImage($color,$width,$height);
329    }
330    //取得图像宽度 @camnpr
331    public function get_width(){$size=$this->image->getImagePage();return $size['width'];}
332    //取得图像高度
333    public function get_height(){$size=$this->image->getImagePage();return $size['height'];}
334    // 设置图像类型
335    public function set_type($type='png'){$this->type=$type;$this->image->setImageFormat($type);}
336    // 取得图像类型
337    public function get_type(){return $this->type;}
338    public function blur($radius,$sigma){$this->image->blurImage($radius,$sigma);} // 模糊
339    public function gaussian_blur($radius,$sigma){$this->image->gaussianBlurImage($radius,$sigma);} // 高斯模糊
340    public function motion_blur($radius,$sigma,$angle){$this->image->motionBlurImage($radius,$sigma,$angle);} // 运动模糊
341    public function radial_blur($radius){$this->image->radialBlurImage($radius);} // 径向模糊
342    public function add_noise($type=null){$this->image->addNoiseImage($type==null?imagick::NOISE_IMPULSE:$type);} // 添加噪点
343    public function level($black_point,$gamma,$white_point){$this->image->levelImage($black_point,$gamma,$white_point);} // 调整色阶
344    public function modulate($brightness,$saturation,$hue){$this->image->modulateImage($brightness,$saturation,$hue);} // 调整亮度,饱和度,色调
345    public function charcoal($radius,$sigma){$this->image->charcoalImage($radius,$sigma);} // 素描效果
346    public function oil_paint($radius){$this->image->oilPaintImage($radius);} // 油画效果
347    public function flop(){$this->image->flopImage();} // 水平翻转
348    public function flip(){$this->image->flipImage();} // 垂直翻转
349}

状况二的解决办法如下:

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

代码如下:
1Version: ImageMagick 6.7.1-2 2014-05-29 Q16 http://www.imagemagick.org
2Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
3Features:  

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

代码如下:
1Version: ImageMagick 6.7.1-2 2014-05-29 Q16 http://www.imagemagick.org
2Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
3Features: openMP

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

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

365据说看到好文章不转的人,服务器容易宕机
原创文章如转载,请注明:转载自郑州网建-前端开发 http://camnpr.com/
本文链接:http://camnpr.com/php-python/1760.html