class EasyPhoto{
//所有图层
private $layers=array();
//当前活动图层
private $ActiveLayer;
//对象实例,单实例模式
private static $instance;
private $imageLayers=array();
public function __construct($fileName=null,$options=array()) {
if(!extension_loaded('gd')){
throw new Exception('需要gd库支持!');
}
if(is_file($fileName)){
$this->addLayer($fileName);
}
}
/*
增加一个图像图层
@param mixed $image 加入图片的完整路径
@param int $x 图层的x坐标
@param int $y图层的y坐标
@param string $pos图层的相对位置,默认是LT
C for center L for left R for right B for bottom T for top
可选值:LT|LC|LB|CT|CC|CB|RT|RC|RB
@param int $opacity图层的透明度
*/
public function addLayer($image,$options=array()){
if(is_string($image)){
$imageName=$image;
$this->imageLayers[]=$imageName;
$image=self::createFromImage($image);
}
$defaults=array(
'x'=>0,
'y'=>0,
'pos'=>'LT',
'opacity'=>100
);
$config=array_merge($defaults,$options);
$this->ActiveLayer=array(
'layer'=>$image,
'width'=>imagesx($image),
'height'=>imagesy($image),
'x'=>$config['x'],
'y'=>$config['y'],
'pos'=>$config['pos'],
'opacity'=>$config['opacity']
);
if(isset($imageName)){
$this->ActiveLayer['name']=$imageName;
}
$this->layers[]=$this->ActiveLayer;
return $this;
}
/*
取得所有图层中最大的宽和高
*/
private function getLayersMaxSize(){
$width=array();
$height=array();
foreach ($this->layers as $layer){
$width[]=$layer['width'];
$height[]=$layer['height'];
}
return array('width'=>max($width),'height'=>max($height));
}
/*
合并所有的图层,图层信息会覆盖成合并后的图层信息
*/
public function mergeLayers(){
$dst_layer=array();
$maxSize=$this->getLayersMaxSize();
foreach ($this->layers as $layer){
if(empty($dst_layer)){
$dst_layer=array(
'width'=>$maxSize['width'],
'height'=>$maxSize['height'],
'x'=>0,
'y'=>0,
'pos'=>'LT',
'opacity'=>100
);
$dst_layer['layer']=self::createTransparentBg($maxSize['width'],$maxSize['height']);
}
$realPosition=self::getRealPosition($maxSize['width'],$maxSize['height'],$layer);
imagecopymerge($dst_layer['layer'], $layer['layer'], $realPosition['x'], $realPosition['y'], 0, 0, $layer['width'], $layer['height'], $layer['opacity']);
}
$this->ActiveLayer=$dst_layer;
$this->layers=array($dst_layer);
return $this;
}
public function setLayerProperty($property=array()){
$index=array_search($this->ActiveLayer, $this->layers);
$this->ActiveLayer=array_merge($this->ActiveLayer,$property);
$this->layers[$index]=$this->ActiveLayer;
return $this;
}
/*
调整图像大小,假如存在多个图层的话,会先合并成一个图层再调整大小
@param int $width 设置的宽度,当为auto时候,直接使用mode 5
@param int $height 设置的高度,当为auto时候,直接使用mode 5
@param array $options 可选参数
@param int $options['mode']调整图片大小的5种模式, default 2
1:直接根据给定的宽高来缩放图形,如果给定的比例不一致会导致图片变形
2:根据给定的宽高,按照原图片的比例全部显示,比例跟原来不一致会差生空白
3:按照图片比例,图像以最大的边显示,多余的部分会去掉,造成生成的缩略图尺寸,其中宽或高会小于指定的
4:图片截取模式,比例不一致时,原图会按原来比例截取,截取中心点可以设定,默认是图片中心点CC
5:给定宽或高按照图片原来比例来调整图片大小
@param string $options['pos'] 截图中心,只在mode 4生效
C for center L for left R for right B for bottom T for top
可选值:LT|LC|LB|CT|CC|CB|RT|RC|RB
*/
public function resize($width,$height,$options=array()){
$default=array(
'mode'=>2,
'pos'=>'CC'
);
$config=array_merge($default,$options=array());
if(count($this->layers)>1){
$this->mergeLayers();
}
if($width=='auto'||$height=='auto'){
$config['mode']=5;
}
switch($config['mode']){
//直接根据给定的宽高来缩放图形,如果给定的比例不一致会导致图片变形
case 1:
$tmpImage=self::createTransparentBg($width, $height);
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], 0, 0, 0, 0, $width, $height, $this->ActiveLayer['width'], $this->ActiveLayer['height']);
break;
//根据给定的宽高,按照原图片的比例全部显示,比例跟原来不一致会差生空白
case 2:
$tmpImage=self::createTransparentBg($width, $height);
$imageWidth=$this->ActiveLayer['width'];
$imageHeight=$this->ActiveLayer['height'];
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$resizeW=$width;
$dstX=0;
$dstY=round(($height-$resizeH)*1.0/2);
}else if($imgRate
$resizeW=round($height*$imageWidth*1.0/$imageHeight);
$resizeH=$height;
$dstY=0;
$dstX=round(($width-$resizeW)*1.0/2);
}else{
$resizeW=$width;
$resizeH=$height;
$dstY=0;
$dstX=0;
}
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], $dstX, $dstY, 0, 0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
//按照图片比例,图像以最大的边显示,多余的部分会去掉,造成生成的缩略图尺寸,其中宽或高会小于指定的
case 3:
$imageWidth=$this->ActiveLayer['width'];
$imageHeight=$this->ActiveLayer['height'];
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$resizeW=$width;
}else if($imgRate
$resizeW=round($height*$imageWidth*1.0/$imageHeight);
$resizeH=$height;
}else{
$resizeW=$width;
$resizeH=$height;
}
$tmpImage=self::createTransparentBg($resizeW, $resizeH);
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], 0, 0, 0, 0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
//图片截取模式,比例不一致时,原图会按原来比例截取,截取中心点可以设定,默认是图片中心点CC
case 4:
$tmpImage=self::createTransparentBg($width, $height);
$imageWidth=$this->ActiveLayer['width'];
$imageHeight=$this->ActiveLayer['height'];
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeW=round($imageWidth*$height*1.0/$imageHeight);
$resizeH=$height;
$dstX=round(($resizeW-$width)*1.0/2);
$dstX=-$dstX;
$dstY=0;
}else if($imgRate
$resizeW=$width;
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$dstX=0;
$dstY=round(($resizeH-$height)*1.0/2);
$dstY=-$dstY;
}else{
$resizeW=$width;
$resizeH=$height;
$dstY=0;
$dstX=0;
}
switch ($config['pos']){
case 'LT':
$dstX=0;
$dstY=0;
break;
case 'LC':
$dstX=0;
break;
case 'LB':
$dstX=0;
$dstY=$dstY*2;
break;
case 'TC':
$dstY=0;
break;
case 'CC':
break;
case 'CB':
$dstY=$dstY*2;
break;
case 'RT':
$dstY=0;
$dstX=$dstX*2;
break;
case 'RC':
$dstX=$dstX*2;
break;
case 'RB':
$dstY=$dstY*2;
$dstX=$dstX*2;
break;
}
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], $dstX, $dstY,0,0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
//给定宽或高按照图片原来比例来调整图片大小
case 5:
$imageWidth=$this->ActiveLayer['width'];
$imageHeight=$this->ActiveLayer['height'];
if($width=='auto'){
$resizeW=round($imageWidth*$height*1.0/$imageHeight);
$resizeH=$height;
}else if($height=='auto'){
$resizeW=$width;
$resizeH=round($imageHeight*$width*1.0/$imageWidth);
}
$tmpImage=self::createTransparentBg($resizeW, $resizeH);
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], 0,0,0,0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
}
$this->ActiveLayer['layer']=$tmpImage;
return $this;
}
public function resizeByPresent($widthPCT,$heightPCT,$options=array()){
$default=array(
'pos'=>'CC',
'mode'=>2
);
$config=array_merge($default,$options);
if(count($this->layers)>1){
$this->mergeLayers();
}
$imageWidth=$this->ActiveLayer['width'];
$imageHeight=$this->ActiveLayer['height'];
$width=$imageWidth*$widthPCT*1.0/100;
$height=$imageHeight*$heightPCT*1.0/100;
if($widthPCT==$heightPCT){
$options['mode']=1;
}
switch($options['mode']){
case 1:
$tmpImage=self::createTransparentBg($width, $height);
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], 0, 0, 0, 0, $width, $height, $imageWidth, $imageHeight);
break;
case 2:
$tmpImage=self::createTransparentBg($width, $height);
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$resizeW=$width;
$dstX=0;
$dstY=round(($height-$resizeH)*1.0/2);
}else if($imgRate
$resizeW=round($height*$imageWidth*1.0/$imageHeight);
$resizeH=$height;
$dstY=0;
$dstX=round(($width-$resizeW)*1.0/2);
}else{
$resizeW=$width;
$resizeH=$height;
$dstY=0;
$dstX=0;
}
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], $dstX, $dstY, 0, 0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
case 3:
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$resizeW=$width;
}else if($imgRate
$resizeW=round($height*$imageWidth*1.0/$imageHeight);
$resizeH=$height;
}else{
$resizeW=$width;
$resizeH=$height;
}
$tmpImage=self::createTransparentBg($resizeW, $resizeH);
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], 0, 0, 0, 0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
case 4:
$tmpImage=self::createTransparentBg($width, $height);
$imgRate=$imageWidth*1.0/$imageHeight;
$resizeRate=$width/$height;
if($imgRate>$resizeRate){
$resizeW=round($imageWidth*$height*1.0/$imageHeight);
$resizeH=$height;
$dstX=round(($resizeW-$width)*1.0/2);
$dstX=-$dstX;
$dstY=0;
}else if($imgRate
$resizeW=$width;
$resizeH=round($width*$imageHeight*1.0/$imageWidth);
$dstX=0;
$dstY=round(($resizeH-$height)*1.0/2);
$dstY=-$dstY;
}else{
$resizeW=$width;
$resizeH=$height;
$dstY=0;
$dstX=0;
}
switch ($config['pos']){
case 'LT':
$dstX=0;
$dstY=0;
break;
case 'LC':
$dstX=0;
break;
case 'LB':
$dstX=0;
$dstY=$dstY*2;
break;
case 'TC':
$dstY=0;
break;
case 'CC':
break;
case 'CB':
$dstY=$dstY*2;
break;
case 'RT':
$dstY=0;
$dstX=$dstX*2;
break;
case 'RC':
$dstX=$dstX*2;
break;
case 'RB':
$dstY=$dstY*2;
$dstX=$dstX*2;
break;
}
$result=imagecopyresampled($tmpImage,$this->ActiveLayer['layer'], $dstX, $dstY,0,0, $resizeW, $resizeH, $imageWidth, $imageHeight);
break;
}
$this->ActiveLayer['layer']=$tmpImage;
return $this;
}
/*
图片剪裁
@param int $width剪裁后的宽度
@param int $height剪裁后的高度
@param array $options可选参数
@param int $options['x'] 相对于pos的x坐标
@param int $options['y'] 相对于pos的y坐标
@param string $options['pos'] 定位中心,以哪个点为参考中心
*/
public function crop($width,$height,$options=array()){
if(count($this->layers)>1){
$this->mergeLayers();
}
$defaults=array(
'x'=>0,
'y'=>0,
'pos'=>'LT'
);
$config=array_merge($defaults,$options);
$dst_image=self::createTransparentBg($width, $height);
$dst_layer=array(
'layer'=>$dst_image,
'width'=>$width,
'height'=>$height,
'x'=>$config['x'],
'y'=>$config['y'],
'pos'=>$config['pos']
);
$cropInfo=array('width'=>$width,'height'=>$height,'x'=>$config['x'],'y'=>$config['y'],'pos'=>$config['pos']);
$realPos=self::getCropPos($dst_layer, $this->ActiveLayer);
imagecopyresampled($dst_layer['layer'], $this->ActiveLayer['layer'], 0, 0, $realPos['x'], $realPos['y'], $width, $height, $width, $height);
$this->ActiveLayer=$dst_layer;
}
/*
保存图片,会自动获取扩展名来保存图片类型
@param string $fileName指定图片保存的完整路径(含路径跟文件名) 如:Uploads/photo/123.png
@param int $quality 指定jpg图片保存的质量,默认100
@param boolean $remove 是否删除使用的图片,默认删除
*/
public function save($fileName,$remove=true,$quality=100){
if(count($this->layers)>1){
$this->mergeLayers();
}
$fileInfo=pathinfo($fileName);
$extension=strtolower($fileInfo['extension']);
switch($extension){
case 'jpg':
imagejpeg($this->ActiveLayer['layer'],$fileName,$quality);
break;
case 'png':
imagepng($this->ActiveLayer['layer'],$fileName);
break;
case 'gif':
imagegif($this->ActiveLayer['layer'],$fileName);
break;
}
imagedestroy($this->ActiveLayer['layer']);
if($remove===true){
foreach ($this->imageLayers as $img){
unlink($img);
}
}
unset($this->ActiveLayer);
unset($this->layers);
unset($this->imageLayers);
$this->layers=array();
$this->imageLayers=array();
}
/*
设置当前图层的level,数值越大的图层越排在前面 (相当于zIndex),当level过大(大于图层数量)时,level值会设置成图层数量
@param int $level 图层的level
*/
public function setLevel($level){
$index=array_search($this->ActiveLayer, $this->layers);
unset($this->layers[$index]);
array_splice($this->layers, $level,0,array($this->ActiveLayer));
return $this;
}
public function topLayer(){
$len=count($this->layers);
$this->setLevel($len);
return $this;
}
/*
根据index值获取图层,并将当前图层替换成取得的图层
@param int $index 如果没设置过图层level的话,图层的index值按照添加的顺序从0-len-1
*/
public function getLayer($index){
$layersLen=count($this->layers);
$index=$index>0?$index:0;
$index=$index
$this->ActiveLayer=$this->layers[$index];
return $this;
}
/*
根据图片的名字获取图层,只支持通过图片创建的图层,并将当前图层替换成取得的图层
@param string $fileName 支持三种模式:1.图片完整的路径;2.图片名字;3.图片名字(不带扩展名)
*/
public function getLayerByFileName($fileName){
foreach ($this->layers as $layer){
if(empty($layer['name'])){
continue;
}
if($layer['name']===$fileName){
$this->ActiveLayer=$layer;
break;
}else{
$fileInfo=pathinfo($layer['name']);
if($fileName===$fileInfo['basename'] || $fileName === $fileInfo['filename']){
$this->ActiveLayer=$layer;
break;
}
}
}
return $this;
}
/*
将web颜色值转化成RGB值
@param string $hex web颜色值
*/
public static function convertHexToRGB($hex){
return array(
'R' => (int) base_convert(substr($hex, 0, 2), 16, 10),
'G' => (int) base_convert(substr($hex, 2, 2), 16, 10),
'B' => (int) base_convert(substr($hex, 4, 2), 16, 10),
);
}
/*
创建一个透明的背景
@param int $width
@param int $height
@param string $color web颜色值
@opacity int $opacity 0-127 127是透明,0是不透明
*/
public static function createTransparentBg($width, $height,$color ='ffffff',$opacity = 127){
$RGBColors = self::convertHexToRGB($color);
$image = imagecreatetruecolor($width, $height);
$color = imagecolorallocatealpha($image, $RGBColors['R'], $RGBColors['G'], $RGBColors['B'],$opacity);
imagecolortransparent($image,$color);
imagefill($image, 0, 0, $color);
return $image;
}
/*
根据图片创建gd image resource
@param string $fileName图像文件的完整路径
*/
public static function createFromImage($fileName){
if(file_exists($fileName)&&!is_dir($fileName)){
$imgInfo=getimagesize($fileName);
$width=$imgInfo[0];
$height=$imgInfo[1];
$type=$imgInfo[2];
if($type>3){
return array('status'=>1,'msg'=>'只支持jpg,png,gif这三种格式的图像文件');
}
switch ($type){
//gif
case 1:
$image=imagecreatefromgif($fileName);
break;
//jpg
case 2:
$image=imagecreatefromjpeg($fileName);
break;
//png
case 3:
$image=imagecreatefrompng($fileName);
break;
}
}else{
throw new Exception('不是一个有效的图像文件');
}
return $image;
}
/*
取得图像图层的绝对位置
@param string $dstW 目标图层的宽
@param string $dstH 目标图层的高
@param array $layer 需要获取绝对位置的图层
*/
public static function getRealPosition($dstW,$dstH,$layer){
$posOut=array();
switch ($layer['pos']){
case 'LT':
$posOut=array('x'=>$layer['x'],'y'=>$layer['y']);
break;
case 'LC':
$offsetH=round(($dstH-$layer['height'])*1.0/2);
$posOut=array('x'=>$layer['x'],'y'=>$offsetH+$layer['y']);
break;
case 'LB':
$offsetH=$dstH-$layer['height'];
$posOut=array('x'=>$layer['x'],'y'=>$offsetH-$layer['y']);
break;
case 'CT':
$offsetW=round(($dstW-$layer['width'])*1.0/2);
$posOut=array('x'=>$offsetW+$layer['x'],'y'=>$layer['y']);
break;
case 'CC':
$offsetW=round(($dstW-$layer['width'])*1.0/2);
$offsetH=round(($dstH-$layer['height'])*1.0/2);
$posOut=array('x'=>$offsetW+$layer['x'],'y'=>$offsetH+$layer['y']);
break;
case 'CB':
$offsetW=round(($dstW-$layer['width'])*1.0/2);
$offsetH=$dstH-$layer['height'];
$posOut=array('x'=>$offsetW+$layer['x'],'y'=>$offsetH-$layer['y']);
break;
case 'RT':
$offsetW=$dstW-$layer['width'];
$posOut=array('x'=>$offsetW-$layer['x'],'y'=>$layer['y']);
break;
case 'RC':
$offsetW=$dstW-$layer['width'];
$offsetH=round(($dstH-$layer['height'])*1.0/2);
$posOut=array('x'=>$offsetW-$layer['x'],'y'=>$offsetH+$layer['y']);
break;
case 'RB':
$offsetW=$dstW-$layer['width'];
$offsetH=$dstH-$layer['height'];
$posOut=array('x'=>$offsetW-$layer['x'],'y'=>$offsetH-$layer['y']);
break;
default:
$posOut=array('x'=>$layer['x'],'y'=>$layer['y']);
break;
}
return $posOut;
}
/*
取得剪裁部分的绝对位置
@param array $cropInfo 剪裁后图层的信息,包含width,height,x,y,pos等信息
@param array $layerInfo 目标图层的信息,包含width,height,x,y,pos等信息
*/
public static function getCropPos($cropInfo,$layerInfo){
switch ($cropInfo['pos']){
case 'LT':
$pos=array('x'=>$cropInfo['x'],'y'=>$cropInfo['y']);
break;
case 'LC':
$offsetHeight=round(($layerInfo['height']-$cropInfo['height'])*1.0/2);
$pos=array('x'=>$cropInfo['x'],'y'=>$cropInfo['y']+$offsetHeight);
break;
case 'LB':
$offsetHeight=$layerInfo['height']-$cropInfo['height'];
$pos=array('x'=>$cropInfo['x'],'y'=>$offsetHeight-$cropInfo['x']);
break;
case 'CT':
$offsetWidth=round(($layerInfo['width']-$cropInfo['width'])*1.0/2);
$pos=array('x'=>$offsetWidth+$cropInfo['x'],'y'=>$cropInfo['y']);
break;
case 'CC':
$offsetWidth=round(($layerInfo['width']-$cropInfo['width'])*1.0/2);
$offsetHeight=round(($layerInfo['height']-$cropInfo['height'])*1.0/2);
$pos=array('x'=>$offsetWidth+$cropInfo['x'],'y'=>$offsetHeight+$cropInfo['y']);
break;
case 'CB':
$offsetWidth=round(($layerInfo['width']-$cropInfo['width'])*1.0/2);
$offsetHeight=$layerInfo['height']-$cropInfo['height'];
$pos=array('x'=>$offsetWidth+$cropInfo['x'],'y'=>$offsetHeight-$cropInfo['y']);
break;
case 'RT':
$offsetWidth=$layerInfo['width']-$cropInfo['width'];
$pos=array('x'=>$offsetWidth-$cropInfo['x'],'y'=>$cropInfo['y']);
break;
case 'RC':
$offsetWidth=$layerInfo['width']-$cropInfo['width'];
$offsetHeight=round(($layerInfo['height']-$cropInfo['height'])*1.0/2);
$pos=array('x'=>$offsetWidth-$cropInfo['x'],'y'=>$offsetHeight+$cropInfo['y']);
break;
case 'RB':
$offsetWidth=$layerInfo['width']-$cropInfo['width'];
$offsetHeight=$layerInfo['height']-$cropInfo['height'];
$pos=array('x'=>$offsetWidth-$cropInfo['x'],'y'=>$offsetHeight-$cropInfo['y']);
break;
}
return $pos;
}
public static function sortLayers($a,$b){
if($a['level']>$b['level']){
return 1;
}else if($a['level']
return -1;
}else{
return 0;
}
}
}
一键复制
编辑
Web IDE
原始数据
按行查看
历史