php Gd库处理合成图片 生成圆角图


png分为png-8、png-24、png-32
当使用imagepng、imagejpeg输出含有PNG-8图片时通道会消失,png-24图片不会发生这个问题;
应该为避免这种情况,应该先把png-8的图片转换成jpg形式,这样颜色通道就能保存下来;

合成:

pubilc function Composite(){
        //$this->pic_base;底图
        //$this->pic;合成图
        //$this->radius;圆角弧度
        //$this->x;合成图 X位置
        //$this->y;合成图 Y位置
        //$this->width;改变合成图的尺寸
        //$this->height;改变合成图的尺寸

        //加入底图
        $pic_base_ext = pathinfo($this->pic_base);//获取图片信息
        switch ($pic_base_ext['extension']) {//根据图片类型  返回图片资源
            case 'jpg':
                $pic_base = imagecreatefromjpeg($this->pic_base);
                break;
            case 'jpeg':
                $pic_base = imagecreatefromjpeg($this->pic_base);
                break;
            case 'png':
                $pic_base = imagecreatefrompng($this->pic_base);
                break;
        }

        list($pic_base_width, $pic_base_height) = getimagesize($this->pic_base);
        //根据底图的尺寸,创建画布
        $image = imagecreatetruecolor($pic_base_width, $pic_base_height);
        //创建背景颜色
        $image_bg = imagecolorallocate($image, 255, 255, 255,127);//127表示透明度,若输出jpg 可以不填,png可以设置
        //填充背景颜色
        imagefill($image, 0, 0, $image_bg);
        imagecopyresized($image, $pic_base, 0, 0, 0, 0, $width, $height, $width, $height);//将底图合并到创建的画布
         
        //加入合成图 商品圆角处理
        $radius_pic = $this->radius_img($this->pic,$this->radius);
        list($pic_width, $pic_height) = getimagesize($this->pic);

        //合成最终图
        imagecopyresized($image, $radius_pic, $this->x, $this->y, 0, 0, $this->width, $this->width, $pic_width, $pic_height);

        imagejpeg($image, $save_path);//保存图,$save_path保存路径 包括对应后缀eg: xxx.jpg
        //imagepng($image, $save_path);//可保存Png

        imagedestroy($pic_base );//销毁底图资源
        imagedestroy($pic );//销毁合成图资源
        
}    

    /**圆角处理 返回文件流
     */
    private function radius_img($imgpath = '', $radius = 20)
    {
        header("Content-Type:image/png");
        $ext = pathinfo($imgpath);
        $src_img = null;
        switch ($ext['extension']) {
            case 'jpg':
                $src_img = imagecreatefromjpeg($imgpath);
                break;
            case 'jpeg':
                $src_img = imagecreatefromjpeg($this->pic);
                break;
            case 'png':
                //大坑 为避免PNG-8合成通道消失 png的先转换jpg 
                $src_img_png = imagecreatefrompng($imgpath);
                $jpg_path = \Yii::$app->runtimePath . '/image/jpg_'.time() . rand(1000, 99999).'.jpg';
                imagejpeg($src_img_png,$jpg_path);
                $src_img = imagecreatefromjpeg($jpg_path);
                break;
        }
        $wh = getimagesize($imgpath);

        $w = $wh[0];
        $h = $wh[1];
        // $radius = $radius == 0 ? (min($w, $h) / 2) : $radius;
        $img = imagecreatetruecolor($w, $h);
        //这一句一定要有
        imagesavealpha($img, true);
        //拾取一个完全透明的颜色,最后一个参数127为全透明
        $bg = imagecolorallocatealpha($img, 255, 255, 255, 127);
        imagefill($img, 0, 0, $bg);

        $r = $radius; //圆 角半径
        for ($x = 0; $x < $w; $x++) {
            for ($y = 0; $y < $h; $y++) {
                $rgbColor = imagecolorat($src_img, $x, $y);//获取像素索引
                if (($x >= $radius && $x <= ($w - $radius)) || ($y >= $radius && $y <= ($h - $radius))) {
                    //不在四角的范围内,直接画
                    imagesetpixel($img, $x, $y, $rgbColor);
                } else {
                    //在四角的范围内选择画
                    //上左
                    $y_x = $r; //圆心X坐标
                    $y_y = $r; //圆心Y坐标
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($r * $r))) {
                        imagesetpixel($img, $x, $y, $rgbColor);
                    }
                    //上右
                    $y_x = $w - $r; //圆心X坐标
                    $y_y = $r; //圆心Y坐标
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($r * $r))) {
                        imagesetpixel($img, $x, $y, $rgbColor);
                    }
                    //下左
                    $y_x = $r; //圆心X坐标
                    $y_y = $h - $r; //圆心Y坐标
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($r * $r))) {
                        imagesetpixel($img, $x, $y, $rgbColor);
                    }
                    //下右
                    $y_x = $w - $r; //圆心X坐标
                    $y_y = $h - $r; //圆心Y坐标
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($r * $r))) {
                        imagesetpixel($img, $x, $y, $rgbColor);
                    }
                }
            }
        }

        unlink($jpg_path);//把临时的文件删了
        return $img;

    }