- 第一种方法:
<?php
function createImg($srcFile) {
$data = getimagesize($srcFile);
switch ($data['2']) {
case 1:
$im = imagecreatefromgif($srcFile);
break;
case 2:
$im = imagecreatefromjpeg($srcFile);
break;
case 3:
$im = imagecreatefrompng($srcFile);
break;
case 6:
$im = imagecreatefromwbmp($srcFile);
break;
}
return $im;
}
/**
* 图片圆角处理函数
*
* @param source $srcImg GD图片资源
* @param integer $radius 圆角大小 = 最短边的长度 / $radius
*/
function roundImgs($srcImg, $radius=2) {
$w = imagesx($srcImg);
$h = imagesy($srcImg);
$radius = min($w, $h) / $radius;
$img = imagecreatetruecolor($w, $h);
imagesavealpha($img, true); // 设置透明通道
$bg = imagecolorallocatealpha($img, 255, 255, 255, 127); // 拾取一个完全透明的颜色, 最后一个参数127为全透明
imagefill($img, 0, 0, $bg);
$r = $radius; // 圆 角半径
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$rgbColor = imagecolorat($srcImg, $x, $y);
if (($x >= $radius && $x <= ($w - $radius)) || ($y >= $radius && $y <= ($h - $radius))) {
imagesetpixel($img, $x, $y, $rgbColor); // 不在四角的范围内,直接画
} else { // 在四角的范围内选择画
// 上左
$yx = $r; // 圆心X坐标
$yy = $r; // 圆心Y坐标
if (((($x - $yx) * ($x - $yx) + ($y - $yy) * ($y - $yy)) <= ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
// 上右
$yx = $w - $r; // 圆心X坐标
$yy = $r; // 圆心Y坐标
if (((($x - $yx) * ($x - $yx) + ($y - $yy) * ($y - $yy)) <= ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
// 下左
$yx = $r; // 圆心X坐标
$yy = $h - $r; // 圆心Y坐标
if (((($x - $yx) * ($x - $yx) + ($y - $yy) * ($y - $yy)) <= ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
// 下右
$yx = $w - $r; // 圆心X坐标
$yy = $h - $r; // 圆心Y坐标
if (((($x - $yx) * ($x - $yx) + ($y - $yy) * ($y - $yy)) <= ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
}
}
}
return $img;
}
function cropImg($img, $axisx, $axisy) {
$width = imagesx($img);
$height = imagesy($img);
$setRatio = $axisx / $axisy;
$curRatio = $width / $height;
if ($setRatio > $curRatio) {
$resizeX = $width;
$resizeY = $resizeX * $axisy / $axisx;
$x = 0;
$y = ($height - $resizeY) / 2;
} elseif ($setRatio < $curRatio) {
$resizeY = $height;
$resizeX = $resizeY * $axisx / $axisy;
$x = ($width - $resizeX) / 2;
$y = 0;
} else {
$resizeX = $width;
$resizeY = $height;
$x = $y = 0;
}
$im = imagecreatetruecolor($resampleX, $resampleY);
imagecopyresampled($im, $img, 0, 0, $x, $y, $resampleX, $resampleY, $resampleX, $resampleY);
imagedestroy($img);
return $im;
}
$url = 'https://upload-images.jianshu.io/upload_images/8396841-829819a83d4a77e4.jpg';
$img = createImg($url); // 创建GD图像资源
$img = cropImg($img, 1, 1); // 为了美观居中裁剪成正方形
$img = roundImgs($img); // 将四个角画成透明的
imagepng($img, './roundBirds.png');
imagedestroy($img);
原图
裁剪后
- 第二种方法:使用PHP Imagick库进行图片圆角处理,Imagick是自带的图片圆角处理,在执行效率上也比GD的要胜上一筹。
/**
* Imagick裁剪圆形图片
*
* @param strimg $imgPath 图片路径
* @param string $saveName 保存路径
* @return source 生成的图片
*/
function roundImg($imgPath, $saveName){
$image = new Imagick($imgPath);
$image->setImageFormat('png');
$width = $image->getImageWidth();
$height = $image->getImageHeight();
$image->roundCorners($width/2, $height/2);
$saveName = $saveName ? : substr(md5(time()), 0, 5).'.png';
$image->writeImage($saveName);
$image->destroy();
}
- 第三种方法:使用PHP GD库进行处理。速度:快。缺点:imagecopyresampled时透明部分会失真,要缩放只能用imagecopyresesize
/**
* 处理圆角图片
* @param srting $imgpath 源图片的路径
* @return [type] [description]
*/
function roundedCorners($imgpath){
list($width,$height,$type) = getimagesize($imgpath);//获取上传图片大小
if ($width != $height) {//如果上传图片不是正方形,取最小宽度作为最终生成图的大小
if ($width > $height) {
$imsize = $height;
} else {
$imsize = $width;
}
}
$im = imagecreatetruecolor($imsize, $imsize);//这里创建第一个图像
$white = imagecolorallocate($im, 255, 255, 255);// 随便取两个颜色,这里取黑色和白色
$black = imagecolorallocate($im, 0, 0, 0);
imagefill($im, 0, 0, $white);//将图片填充为白色
imagefilledellipse($im, $imsize/2, $imsize/2, $imsize, $imsize, $black);//然后再图片中间画一个黑色的圆
imagecolortransparent($im, $black);//将黑色设为透明的,则现在四个角是白色的,然后中间是透明的
switch ($type) {
case '2':
$img = imagecreatefromjpeg($imgpath);//这里创建的是第二个图像
break;
default:
$img = imagecreatefrompng($imgpath);//这里创建的是第二个图像
break;
}
$final = imagecreatetruecolor($imsize, $imsize);//再创建一个图像,第三个图像
imagecopyresampled($final, $img, 0, 0, ($width-$imsize)/2, ($height-$imsize)/2, $imsize, $imsize, $imsize, $imsize);//先将第二个图像(图片)压在空白的图像上,根据最小宽度,居中裁剪,成为第四个图像
imagecopymerge($final, $im, 0, 0, 0, 0, $imsize, $imsize, 100);//再将第一个图像压在第四个图像上,由于中间是透明的,所以现在图像上中间是图片,四个角都是白色的,第五个图
imagecolortransparent($im, $white);//然后将白色设置为透明的,现在这个图四个角是透明的,然后中间是黑色的
imagecopymerge($im, $final, 0, 0, 0, 0, $imsize, $imsize, 100);//将第五个图压在最后的图像上,就可以得到最后的圆形的图了
return $im;//返回图片
}
- 要裁剪不规则图形则需要借助另外的图片来完成任务。需要借助二值图作为模板图,或者给出的模板图片上,要抠出来的部分须为不透明的,要去掉的部分则为透明的,传入模板图片和原始图片地址,返回一个图片资源。
/**
* 根据给出的模板抠图
* @param string $templateImgUrl 模板图片地址
* @param string $userImgUrl 原始图片地址
* @return source $img 图片资源
*/
function createImg($srcFile) {
$data = getimagesize($srcFile);
switch ($data['2']) {
case 1:
$im = imagecreatefromgif($srcFile);
break;
case 2:
$im = imagecreatefromjpeg($srcFile);
break;
case 3:
$im = imagecreatefrompng($srcFile);
break;
case 6:
$im = imagecreatefromwbmp($srcFile);
break;
}
return $im;
}
function cropImgByTemplate($templateImgUrl, $userImgUrl) {
list($w, $h) = getimagesize($userImgUrl);
$uimg = createImg($userImgUrl);
$tempImg = imagecreatefrompng($templateImgUrl);
list($width,$height) = getimagesize($templateImgUrl);
$uim = imagecreatetruecolor($width, $height); // 将用户图片的尺寸大小缩放到模板的大小方便裁剪
imagecopyresampled($uim, $uimg, 0, 0, 0, 0, $width, $height, $w, $h);
$img = imagecreatetruecolor($width, $height); // 创建一个底图,大小和模板一致
imagesavealpha($img, true); // 设置alpha通道为true,显示透明部分
$bg = imagecolorallocatealpha($img, 255, 255, 255, 127); // 摄取一个透明的颜色
imagefill($img, 0, 0, $bg); // 将透明颜色填满底图,得到一张全透明的图片
for ($i=0; $i < $width; $i++) { // 遍历图片的像素点
for ($j=0; $j < $height; $j++) {
$rgb = imagecolorat($tempImg, $i, $j); // 获取模板上某个点的色值
if (!$rgb) { // 不是透明的
$color = imagecolorat($uim, $i, $j); // 在用户的图片上对应的地方取色值
imagesetpixel($img, $i, $j, $color); // 在透明底图上画出要裁剪出来的部分
}
}
}
return $img;
}
$tempUrl = 'https://upload-images.jianshu.io/upload_images/8396841-50c151628048a0cf.png';
$url = 'https://upload-images.jianshu.io/upload_images/8396841-829819a83d4a77e4.jpg';
$img = cropImgByTemplate($tempUrl, $url);
imagepng($img, './test.png');
imagedestroy($img);
模板图
原图
裁剪结果