美文网首页
PHP 裁剪图片成圆形、不规则形状

PHP 裁剪图片成圆形、不规则形状

作者: 达莎雕 | 来源:发表于2019-06-02 20:17 被阅读0次
    • 第一种方法:
    <?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://img.haomeiwen.com/i8396841/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://img.haomeiwen.com/i8396841/50c151628048a0cf.png';
    $url = 'https://img.haomeiwen.com/i8396841/829819a83d4a77e4.jpg';
    $img = cropImgByTemplate($tempUrl, $url);
    imagepng($img, './test.png');
    imagedestroy($img);
    
    模板图 原图 裁剪结果

    相关文章

      网友评论

          本文标题:PHP 裁剪图片成圆形、不规则形状

          本文链接:https://www.haomeiwen.com/subject/fvhfxctx.html