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图像处理类
用法:
//引入Imagick物件
if(!defined('CLASS_IMAGICK')){require(Inc.'class_imagick.php');}
$Imagick=new class_imagick();
$Imagick->open('a.gif');
$Imagick->resize_to(100,100,'scale_fill');
$Imagick->add_text('1024i.com',10,20);
$Imagick->add_watermark('1024i.gif',10,50);
$Imagick->save_to('x.gif');
unset($Imagick);
/**/
define('CLASS_IMAGICK',TRUE);
class class_imagick{
private $image=null;
private $type=null;
// 构造
public function __construct(){}
// 析构
public function __destruct(){
if($this->image!==null){$this->image->destroy();}
}
// 载入图像
public function open($path){
if(!file_exists($path)){
$this->image=null;
return ;
}
$this->image=new Imagick($path);
if($this->image){
$this->type=strtolower($this->image->getImageFormat());
}
$this->image->stripImage();
return $this->image;
}
/**
图像裁切
/**/
public function crop($x=0,$y=0,$width=null,$height=null){
if($width==null) $width=$this->image->getImageWidth()-$x;
if($height==null) $height=$this->image->getImageHeight()-$y;
if($width if($this->type=='gif'){
$image=$this->image;
$canvas=new Imagick();
$images=$image->coalesceImages();
foreach($images as $frame){
$img=new Imagick();
$img->readImageBlob($frame);
$img->cropImage($width,$height,$x,$y);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
$canvas->setImagePage($width,$height,0,0);
}
$image->destroy();
$this->image=$canvas;
}else{
$this->image->cropImage($width,$height,$x,$y);
}
}
/**
更改图像大小
参数:
$width:新的宽度
$height:新的高度
$fit: 适应大小
'force': 把图像强制改为$width X $height
'scale': 按比例在$width X $height内缩放图片,结果不完全等於$width X $height
'scale_fill':按比例在$width X $height内缩放图片,没有像素的地方填充顏色$fill_color=array(255,255,255)(红,绿,蓝,透明度[0不透明-127全透明])
其他:智能模式,缩放图片并从正中裁切$width X $height的大小
注意:
$fit='force','scale','scale_fill'时输出完整图像
$fit=图像方位时输出指定位置部份的图像
字母与图像的对应关系如下:
north_west north north_east
west center east
south_west south south_east
/**/
public function resize_to($width=100,$height=100,$fit='center',$fill_color=array(255,255,255,0)){
switch($fit){
case 'force':
if($this->type=='gif'){
$image=$this->image;
$canvas=new Imagick();
$images=$image->coalesceImages();
foreach($images as $frame){
$img=new Imagick();
$img->readImageBlob($frame);
$img->thumbnailImage($width,$height,false);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
}
$image->destroy();
$this->image=$canvas;
}else{
$this->image->thumbnailImage($width,$height,false);
}
break;
case 'scale':
if($this->type=='gif'){
$image=$this->image;
$images=$image->coalesceImages();
$canvas=new Imagick();
foreach($images as $frame){
$img=new Imagick();
$img->readImageBlob($frame);
$img->thumbnailImage($width,$height,true);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
}
$image->destroy();
$this->image=$canvas;
}else{
$this->image->thumbnailImage($width,$height,true);
}
break;
case 'scale_fill':
$size=$this->image->getImagePage();
$src_width=$size['width'];
$src_height=$size['height'];
$x=0;
$y=0;
$dst_width=$width;
$dst_height=$height;
if($src_width*$height > $src_height*$width){
$dst_height=intval($width*$src_height/$src_width);
$y=intval(($height-$dst_height)/2);
}else{
$dst_width=intval($height*$src_width/$src_height);
$x=intval(($width-$dst_width)/2);
}
$image=$this->image;
$canvas=new Imagick();
$color='rgba('.$fill_color[0].','.$fill_color[1].','.$fill_color[2].','.$fill_color[3].')';
if($this->type=='gif'){
$images=$image->coalesceImages();
foreach($images as $frame){
$frame->thumbnailImage($width,$height,true);
$draw=new ImagickDraw();
$draw->composite($frame->getImageCompose(),$x,$y,$dst_width,$dst_height,$frame);
$img=new Imagick();
$img->newImage($width,$height,$color,'gif');
$img->drawImage($draw);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
$canvas->setImagePage($width,$height,0,0);
}
}else{
$image->thumbnailImage($width,$height,true);
$draw=new ImagickDraw();
$draw->composite($image->getImageCompose(),$x,$y,$dst_width,$dst_height,$image);
$canvas->newImage($width,$height,$color,$this->get_type());
$canvas->drawImage($draw);
$canvas->setImagePage($width,$height,0,0);
}
$image->destroy();
$this->image=$canvas;
break;
default:
$size=$this->image->getImagePage();
$src_width=$size['width'];
$src_height=$size['height'];
$crop_x=0;
$crop_y=0;
$crop_w=$src_width;
$crop_h=$src_height;
if($src_width*$height > $src_height*$width){
$crop_w=intval($src_height*$width/$height);
}else{
$crop_h=intval($src_width*$height/$width);
}
switch($fit){
case 'north_west':
$crop_x=0;
$crop_y=0;
break;
case 'north':
$crop_x=intval(($src_width-$crop_w)/2);
$crop_y=0;
break;
case 'north_east':
$crop_x=$src_width-$crop_w;
$crop_y=0;
break;
case 'west':
$crop_x=0;
$crop_y=intval(($src_height-$crop_h)/2);
break;
case 'center':
$crop_x=intval(($src_width-$crop_w)/2);
$crop_y=intval(($src_height-$crop_h)/2);
break;
case 'east':
$crop_x=$src_width-$crop_w;
$crop_y=intval(($src_height-$crop_h)/2);
break;
case 'south_west':
$crop_x=0;
$crop_y=$src_height-$crop_h;
break;
case 'south':
$crop_x=intval(($src_width-$crop_w)/2);
$crop_y=$src_height-$crop_h;
break;
case 'south_east':
$crop_x=$src_width-$crop_w;
$crop_y=$src_height-$crop_h;
break;
default:
$crop_x=intval(($src_width-$crop_w)/2);
$crop_y=intval(($src_height-$crop_h)/2);
}
$image=$this->image;
$canvas=new Imagick();
if($this->type=='gif'){
$images=$image->coalesceImages();
foreach($images as $frame){
$img=new Imagick();
$img->readImageBlob($frame);
$img->cropImage($crop_w,$crop_h,$crop_x,$crop_y);
$img->thumbnailImage($width,$height,true);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
$canvas->setImagePage($width,$height,0,0);
}
}else{
$image->cropImage($crop_w,$crop_h,$crop_x,$crop_y);
$image->thumbnailImage($width,$height,true);
$canvas->addImage($image);
$canvas->setImagePage($width,$height,0,0);
}
$image->destroy();
$this->image=$canvas;
}
}
/**
添加图片水印
参数:
$path:水印图片(包含完整路径)
$x,$y:水印座标
/**/
public function add_watermark($path,$x=0,$y=0){
$watermark=new Imagick($path);
$draw=new ImagickDraw();
$draw->composite($watermark->getImageCompose(),$x,$y,$watermark->getImageWidth(),$watermark->getimageheight(),$watermark);
if($this->type=='gif'){
$image=$this->image;
$canvas=new Imagick();
$images=$image->coalesceImages();
foreach($image as $frame){
$img=new Imagick();
$img->readImageBlob($frame);
$img->drawImage($draw);
$canvas->addImage($img);
$canvas->setImageDelay($img->getImageDelay());
}
$image->destroy();
$this->image=$canvas;
}else{
$this->image->drawImage($draw);
}
}
/**
添加文字水印
参数:
$text:水印文字
$x,$y:水印座标
/**/
public function add_text($text,$x=0,$y=0,$angle=0,$style=array()){
$draw=new ImagickDraw();
if(isset($style['font'])) $draw->setFont($style['font']);
if(isset($style['font_size'])) $draw->setFontSize($style['font_size']);
if(isset($style['fill_color'])) $draw->setFillColor($style['fill_color']);
if(isset($style['under_color'])) $draw->setTextUnderColor($style['under_color']);
if($this->type=='gif'){
foreach($this->image as $frame){
$frame->annotateImage($draw,$x,$y,$angle,$text);
}
}else{
$this->image->annotateImage($draw,$x,$y,$angle,$text);
}
}
/**
图片存档
参数:
$path:存档的位置和新的档案名
/**/
public function save_to($path){
$this->image->stripImage();
switch($this->type){
case 'gif':
$this->image->writeImages($path,true);
return ;
case 'jpg':
case 'jpeg':
$this->image->setImageCompressionQuality($_ENV['ImgQ']);
$this->image->writeImage($path);
return ;
case 'png':
$flag = $this->image->getImageAlphaChannel();
// 如果png背景不透明则压缩
if(imagick::ALPHACHANNEL_UNDEFINED == $flag or imagick::ALPHACHANNEL_DEACTIVATE == $flag){
$this->image->setImageType(imagick::IMGTYPE_PALETTE);
$this->image->writeImage($path);
}else{
$this->image->writeImage($path);
}unset($flag);
return ;
default:
$this->image->writeImage($path);
return ;
}
}
// 直接输出图像到萤幕
public function output($header=true){
if($header) header('Content-type: '.$this->type);
echo $this->image->getImagesBlob();
}
/**
建立缩小图
$fit为真时,将保持比例并在$width X $height内產生缩小图
/**/
public function thumbnail($width=100,$height=100,$fit=true){$this->image->thumbnailImage($width,$height,$fit);}
/**
给图像添加边框
$width: 左右边框宽度
$height: 上下边框宽度
$color: 顏色
/**/
public function border($width,$height,$color='rgb(220,220,220)'){
$color=new ImagickPixel();
$color->setColor($color);
$this->image->borderImage($color,$width,$height);
}
//取得图像宽度
public function get_width(){$size=$this->image->getImagePage();return $size['width'];}
//取得图像高度
public function get_height(){$size=$this->image->getImagePage();return $size['height'];}
// 设置图像类型
public function set_type($type='png'){$this->type=$type;$this->image->setImageFormat($type);}
// 取得图像类型
public function get_type(){return $this->type;}
public function blur($radius,$sigma){$this->image->blurImage($radius,$sigma);} // 模糊
public function gaussian_blur($radius,$sigma){$this->image->gaussianBlurImage($radius,$sigma);} // 高斯模糊
public function motion_blur($radius,$sigma,$angle){$this->image->motionBlurImage($radius,$sigma,$angle);} // 运动模糊
public function radial_blur($radius){$this->image->radialBlurImage($radius);} // 径向模糊
public function add_noise($type=null){$this->image->addNoiseImage($type==null?imagick::NOISE_IMPULSE:$type);} // 添加噪点
public function level($black_point,$gamma,$white_point){$this->image->levelImage($black_point,$gamma,$white_point);} // 调整色阶
public function modulate($brightness,$saturation,$hue){$this->image->modulateImage($brightness,$saturation,$hue);} // 调整亮度,饱和度,色调
public function charcoal($radius,$sigma){$this->image->charcoalImage($radius,$sigma);} // 素描效果
public function oil_paint($radius){$this->image->oilPaintImage($radius);} // 油画效果
public function flop(){$this->image->flopImage();} // 水平翻转
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之后一切正常,而且处理图像的效能比之以前有了大幅提升

使用数据库存储会话的主要优势包括持久性、可扩展性和安全性。1.持久性:即使服务器重启,会话数据也能保持不变。2.可扩展性:适用于分布式系统,确保会话数据在多服务器间同步。3.安全性:数据库提供加密存储,保护敏感信息。

在PHP中实现自定义会话处理可以通过实现SessionHandlerInterface接口来完成。具体步骤包括:1)创建实现SessionHandlerInterface的类,如CustomSessionHandler;2)重写接口中的方法(如open,close,read,write,destroy,gc)来定义会话数据的生命周期和存储方式;3)在PHP脚本中注册自定义会话处理器并启动会话。这样可以将数据存储在MySQL、Redis等介质中,提升性能、安全性和可扩展性。

SessionID是网络应用程序中用来跟踪用户会话状态的机制。1.它是一个随机生成的字符串,用于在用户与服务器之间的多次交互中保持用户的身份信息。2.服务器生成并通过cookie或URL参数发送给客户端,帮助在用户的多次请求中识别和关联这些请求。3.生成通常使用随机算法保证唯一性和不可预测性。4.在实际开发中,可以使用内存数据库如Redis来存储session数据,提升性能和安全性。

在无状态环境如API中管理会话可以通过使用JWT或cookies来实现。1.JWT适合无状态和可扩展性,但大数据时体积大。2.Cookies更传统且易实现,但需谨慎配置以确保安全性。

要保护应用免受与会话相关的XSS攻击,需采取以下措施:1.设置HttpOnly和Secure标志保护会话cookie。2.对所有用户输入进行输出编码。3.实施内容安全策略(CSP)限制脚本来源。通过这些策略,可以有效防护会话相关的XSS攻击,确保用户数据安全。

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显着提升应用在高并发环境下的效率。

thesession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceIsiseededeedeedeedeedeedeedto to to avoidperformance andununununununexpectedLogOgouts.3)

在PHP中,可以使用session_name()函数配置会话名称。具体步骤如下:1.使用session_name()函数设置会话名称,例如session_name("my_session")。2.在设置会话名称后,调用session_start()启动会话。配置会话名称可以避免多应用间的会话数据冲突,并增强安全性,但需注意会话名称的唯一性、安全性、长度和设置时机。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Atom编辑器mac版下载
最流行的的开源编辑器

禅工作室 13.0.1
功能强大的PHP集成开发环境