fastadmin 生成邀请海报

生成二维码和邀请海报

方案一
php 复制代码
if(!function_exists('createInviteImg')){
    // 生成推广员邀请码图片
	function createInviteImg($promoter_code, $promoter_name, $promoter_code_id){
        // 邀请海报背景图
        $inviteBgImg = '/assets/img/inviteBgImg.png';        
        $site = Config::get("site");
        if(array_key_exists('inviteBgImg',$site)){
            $inviteBgImg = $site['inviteBgImg'];
        }
        
        // 生成二维码
        $text = cdnurl("/promoter_invite?promoter_code=".$promoter_code,true); // 微信扫码跳转到小程序
        list($filePath,$fileUrl) = buildQrcode($text, '', '/uploads/qrcode/promoter/', 'code_'.$promoter_code_id.'_'.time(), true, 20);
        
        // 生成邀请海报
        $fileUrl = '/uploads/qrcode/promoter/promoter_'. $promoter_code_id.'_'.time().'.jpg';
        $filename = ROOT_PATH .'public'. $fileUrl;
        $config = array(
            'image'=>array(
                array(
                    'url'=>$filePath,     //二维码地址
                    'stream'=>0,
                    'left'=>-1,               //小于0为小平居中                             
                    'top'=>927,
                    'right'=>0,
                    'width'=>284,             //图像宽
                    'height'=>284,            //图像高
                    'opacity'=>100,            //透明度
                ),
            ),
            'text'=>array(
                array(
                    'text'=>'邀请码:'.$promoter_code,            //文字内容
                    'left'=>-1,                              //小于0为水平居中      
                    'top'=>910,
                    'fontSize'=>20,                         //字号
                    'fontColor'=>'255,255,255',                //字体颜色
                    'angle'=>0,
                    'fontPath'=>ROOT_PATH.'public/assets/fonts/msyh/msyh.ttf',     //字体文件
                )
            ),
            'background'=>ROOT_PATH.'public'.$inviteBgImg,          //背景图
            // 'background'=>cdnurl('/assets/img/haibao.png',true),          //背景图
        );

        //echo createPoster($config);
        //$filename为空是真接浏览器显示图片
        createPoster($config,$filename);
            
        // 删除二维码文件
        @unlink($filePath); 

        return $fileUrl;
        // return cdnurl($fileUrl,true);
    }

}


if (!function_exists('buildQrcode')) {
    // 生成二维码
    function buildQrcode($text, $label, $file_url, $name='', $rounded=true, $radius = 20)
    {
        $params = [
            'text'           => $text,
            'size'           => 284,    //大小
            'padding'        => 7,    //内边距
            'errorlevel'     => 'medium',   //容错级别:low-低   medium-中等   quartile-高   high-超高
            'foreground'     => "#000000",     //前景色
            'background'     => "#ffffff",  //背景色
            'logo'           => 0,    //Logo:1-显示,0-不显示
            'logosize'       => '',  //Logo大小
            'label'          => $label, //标签
            'labelfontsize'  => 16, //标签大小
            'labelalignment' => 'center',    //标签水平位置:left-左  center-中   right-右
        ];

        $qrCode = \addons\qrcode\library\Service::qrcode($params);

        $response = Response::create()->header("Content-Type", "image/png");

        // 直接显示二维码
        header('Content-Type: ' . $qrCode->getMimeType());
        $response->content($qrCode->getString());

        // 写入到文件
        $file_name = $name?$name:md5(implode('', $params));
        $fileUrl = $file_url . $file_name . '.png';
        $filePath = ROOT_PATH .'public'. $fileUrl;
        if (!file_exists(ROOT_PATH .'public/uploads/qrcode/')) mkdir (ROOT_PATH .'public/uploads/qrcode/',0777,true); 
        if (!file_exists(ROOT_PATH .'public'.$file_url)) mkdir (ROOT_PATH .'public'.$file_url,0777,true); 
        
        $qrCode->saveToFile($filePath);

        // 如果启用圆角,处理二维码图片
        if ($rounded) {
            $roundedFilePath = ROOT_PATH . 'public' . $file_url . $file_name . '_rounded.png';
            $roundedFileUrl = $file_url . $file_name . '_rounded.png';
            
            // 生成圆角二维码
            $result = applyRoundedCornersToImage($filePath, $roundedFilePath, $radius);
            
            if ($result) {
                @unlink($filePath);
                // 使用圆角二维码文件路径
                $filePath = $roundedFilePath;
                $fileUrl = $roundedFileUrl;
            }
        }

        return [$filePath,$fileUrl];
    }
}

/**
 * 给图片添加圆角
 * @param string $sourcePath 源图片路径
 * @param string $destPath 目标图片路径
 * @param int $radius 圆角半径
 * @return bool 是否成功
 */
function applyRoundedCornersToImage($sourcePath, $destPath, $radius = 20) {
    // 获取图片信息
    $info = getimagesize($sourcePath);
    if ($info === false) {
        return false;
    }
    
    // 根据图片类型创建图像资源
    $imageType = $info[2];
    switch ($imageType) {
        case IMAGETYPE_PNG:
            $sourceImage = imagecreatefrompng($sourcePath);
            break;
        case IMAGETYPE_JPEG:
            $sourceImage = imagecreatefromjpeg($sourcePath);
            break;
        case IMAGETYPE_GIF:
            $sourceImage = imagecreatefromgif($sourcePath);
            break;
        default:
            return false;
    }
    
    if (!$sourceImage) {
        return false;
    }
    
    $width = imagesx($sourceImage);
    $height = imagesy($sourceImage);
    
    // 创建新图像
    $roundedImage = imagecreatetruecolor($width, $height);
    
    // 设置透明背景
    imagealphablending($roundedImage, false);
    imagesavealpha($roundedImage, true);
    $transparent = imagecolorallocatealpha($roundedImage, 0, 0, 0, 127);
    imagefill($roundedImage, 0, 0, $transparent);
    
    // 创建圆角遮罩
    $mask = imagecreatetruecolor($width, $height);
    $white = imagecolorallocate($mask, 255, 255, 255);
    $black = imagecolorallocate($mask, 0, 0, 0);
    imagefill($mask, 0, 0, $white);
    
    // 绘制黑色圆角矩形(这是我们要保留的区域)
    drawRoundedRect($mask, 0, 0, $width, $height, $radius, $black);
    
    // 应用遮罩
    for ($x = 0; $x < $width; $x++) {
        for ($y = 0; $y < $height; $y++) {
            $maskColor = imagecolorat($mask, $x, $y);
            $maskRgb = imagecolorsforindex($mask, $maskColor);
            
            // 如果遮罩是黑色(在圆角矩形内),复制原图像素
            if ($maskRgb['red'] == 0 && $maskRgb['green'] == 0 && $maskRgb['blue'] == 0) {
                $srcColor = imagecolorat($sourceImage, $x, $y);
                $srcRgb = imagecolorsforindex($sourceImage, $srcColor);
                
                $newColor = imagecolorallocatealpha(
                    $roundedImage,
                    $srcRgb['red'],
                    $srcRgb['green'],
                    $srcRgb['blue'],
                    $srcRgb['alpha']
                );
                
                imagesetpixel($roundedImage, $x, $y, $newColor);
            }
        }
    }
    
    // 保存圆角图片
    imagepng($roundedImage, $destPath, 9);
    
    // 释放资源
    imagedestroy($sourceImage);
    imagedestroy($roundedImage);
    imagedestroy($mask);
    
    return true;
}

/**
 * 绘制圆角矩形
 */
function drawRoundedRect($image, $x, $y, $width, $height, $radius, $color) {
    // 确保半径不超过矩形的一半
    $radius = min($radius, floor($width / 2), floor($height / 2));
    
    // 绘制四个圆角
    imagefilledarc($image, $x + $radius, $y + $radius, $radius * 2, $radius * 2, 180, 270, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $width - $radius, $y + $radius, $radius * 2, $radius * 2, 270, 360, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $width - $radius, $y + $height - $radius, $radius * 2, $radius * 2, 0, 90, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $radius, $y + $height - $radius, $radius * 2, $radius * 2, 90, 180, $color, IMG_ARC_PIE);
    
    // 绘制矩形部分
    imagefilledrectangle($image, $x + $radius, $y, $x + $width - $radius, $y + $radius, $color);
    imagefilledrectangle($image, $x, $y + $radius, $x + $radius, $y + $height - $radius, $color);
    imagefilledrectangle($image, $x + $radius, $y + $height - $radius, $x + $width - $radius, $y + $height, $color);
    imagefilledrectangle($image, $x + $width - $radius, $y + $radius, $x + $width, $y + $height - $radius, $color);
    
    // 填充中间区域
    imagefilledrectangle($image, $x + $radius, $y + $radius, $x + $width - $radius, $y + $height - $radius, $color);
}

if (!function_exists('createPoster')) {
    /**
     * 生成宣传海报(优化版,正确处理透明PNG)
     */
    function createPoster($config = array(), $filename = "") {
        if (empty($filename)) {
            header("content-type: image/png");
        }
        
        // 默认图片参数
        $imageDefault = array(
            'left' => 0,
            'top' => 0,
            'right' => 0,
            'bottom' => 0,
            'width' => 100,
            'height' => 100,
            'opacity' => 100
        );
        
        // 默认文字参数
        $textDefault = array(
            'text' => '',
            'left' => 0,
            'top' => 0,
            'fontSize' => 32,
            'fontColor' => '255,255,255',
            'angle' => 0,
        );
        
        // 加载背景图片
        $backgroundPath = $config['background'];
        if (!file_exists($backgroundPath)) {
            die('背景图片不存在: ' . $backgroundPath);
        }
        
        $background = imagecreatefromstring(file_get_contents($backgroundPath));
        if (!$background) {
            die('无法加载背景图片');
        }
        
        $backgroundWidth = imagesx($background);
        $backgroundHeight = imagesy($background);
        
        // 创建海报画布
        $poster = imagecreatetruecolor($backgroundWidth, $backgroundHeight);
        
        // 复制背景到海报
        imagecopy($poster, $background, 0, 0, 0, 0, $backgroundWidth, $backgroundHeight);
        
        // 处理图片元素
        if (!empty($config['image'])) {
            foreach ($config['image'] as $val) {
                $val = array_merge($imageDefault, $val);
                
                // 加载图片
                if (!file_exists($val['url'])) {
                    continue;
                }
                
                $imageContent = file_get_contents($val['url']);
                if (!$imageContent) {
                    continue;
                }
                
                $srcImage = imagecreatefromstring($imageContent);
                if (!$srcImage) {
                    continue;
                }
                
                $srcWidth = imagesx($srcImage);
                $srcHeight = imagesy($srcImage);
                
                // 创建临时画布
                $tempCanvas = imagecreatetruecolor($val['width'], $val['height']);
                
                // 设置透明背景
                imagesavealpha($tempCanvas, true);
                imagealphablending($tempCanvas, false);
                $transparent = imagecolorallocatealpha($tempCanvas, 0, 0, 0, 127);
                imagefill($tempCanvas, 0, 0, $transparent);
                
                // 重新采样图片
                imagecopyresampled($tempCanvas, $srcImage, 0, 0, 0, 0, $val['width'], $val['height'], $srcWidth, $srcHeight);
                
                // 计算位置
                if ($val['left'] < 0) {
                    $val['left'] = ceil(($backgroundWidth - $val['width']) / 2);
                }
                
                if ($val['top'] < 0) {
                    $val['top'] = ceil(($backgroundHeight - $val['height']) / 2);
                }
                
                // 合并到海报
                imagecopy($poster, $tempCanvas, $val['left'], $val['top'], 0, 0, $val['width'], $val['height']);
                
                imagedestroy($srcImage);
                imagedestroy($tempCanvas);
            }
        }
        
        // 处理文字
        if (!empty($config['text'])) {
            foreach ($config['text'] as $val) {
                $val = array_merge($textDefault, $val);
                
                // 设置字体颜色
                list($R, $G, $B) = explode(',', $val['fontColor']);
                $fontColor = imagecolorallocate($poster, $R, $G, $B);
                
                // 计算文字位置
                if ($val['left'] < 0) {
                    // 水平居中
                    $fontPath = isset($val['fontPath']) ? $val['fontPath'] : '';
                    if ($fontPath && file_exists($fontPath)) {
                        $bbox = imagettfbbox($val['fontSize'], $val['angle'], $fontPath, $val['text']);
                        if ($bbox) {
                            $textWidth = $bbox[2] - $bbox[0];
                            $val['left'] = ceil(($backgroundWidth - $textWidth) / 2);
                        }
                    }
                }
                
                // 添加文字
                if (isset($val['fontPath']) && file_exists($val['fontPath'])) {
                    imagettftext($poster, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
                }
            }
        }
        
        // 输出或保存图片
        if (!empty($filename)) {
            // 确保目录存在
            $dir = dirname($filename);
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
            
            // 保存为JPEG
            imagejpeg($poster, $filename, 90);
            imagedestroy($poster);
            imagedestroy($background);
            
            return file_exists($filename) ? $filename : false;
        } else {
            // 直接输出
            header('Content-Type: image/jpeg');
            imagejpeg($poster);
            imagedestroy($poster);
            imagedestroy($background);
            exit;
        }
    }
}

// 不能生成显示出二维码的圆角(不能正确处理透明PNG)
// if (!function_exists('createPoster')) {
//     /**
//      * 生成宣传海报
//      * @param array  参数,包括图片和文字
//      * @param string  $filename 生成海报文件名,不传此参数则不生成文件,直接输出图片
//      * @return [type] [description]
//      */
//     function createPoster($config = array() , $filename = "") {
//         if (empty($filename)) header("content-type: image/png");
//         $imageDefault = array(
//             'left' => 0,
//             'top' => 0,
//             'right' => 0,
//             'bottom' => 0,
//             'width' => 100,
//             'height' => 100,
//             'opacity' => 100,
//             'radius' => 0, // 新增:圆角半径,0表示直角
//             'is_yuan' => false // 兼容旧参数,圆形裁剪
//         );
//         $textDefault = array(
//             'text' => '',
//             'left' => 0,
//             'top' => 0,
//             'fontSize' => 32, //字号
//             'fontColor' => '255,255,255', //字体颜色
//             'angle' => 0,
//         );
//         $background = $config['background']; //海报最底层得背景
//         //背景方法
//         $backgroundInfo = getimagesize($background);
//         $backgroundFun = 'imagecreatefrom' . image_type_to_extension($backgroundInfo[2], false);
//         $background = $backgroundFun($background);
//         $backgroundWidth = imagesx($background); //背景宽度
//         $backgroundHeight = imagesy($background); //背景高度
//         $imageRes = imageCreatetruecolor($backgroundWidth, $backgroundHeight);
//         $color = imagecolorallocate($imageRes, 255, 255, 255);  //背景图默认填充颜色为白色
//         imagefill($imageRes, 0, 0, $color);
//         imagecopyresampled($imageRes, $background, 0, 0, 0, 0, imagesx($background) , imagesy($background) , imagesx($background) , imagesy($background));
//         //处理了图片
//         if (!empty($config['image'])) {
//             foreach ($config['image'] as $key => $val) {
//                 $val = array_merge($imageDefault, $val);
//                 $info = getimagesize($val['url']);
//                 $function = 'imagecreatefrom' . image_type_to_extension($info[2], false);
//                 if ($val['stream']) { //如果传的是字符串图像流
//                     $info = getimagesizefromstring($val['url']);
//                     $function = 'imagecreatefromstring';
//                 }
//                 $res = $function($val['url']);
//                 $resWidth = $info[0];
//                 $resHeight = $info[1];
//                 //建立画板 ,缩放图片至指定尺寸
//                 $canvas = imagecreatetruecolor($val['width'], $val['height']);
//                 imagefill($canvas, 0, 0, $color);
//                 //如果是透明的gif或png做透明处理
//                 $ext = pathinfo($val['url']);
//                 if (array_key_exists('extension',$ext)) {
//                     if ($ext['extension'] == 'gif' || $ext['extension'] == 'png') {
//                         // imageColorTransparent($canvas, $color); //颜色透明                     
//                     }
//                 }
//                 //关键函数,参数(目标资源,源,目标资源的开始坐标x,y, 源资源的开始坐标x,y,目标资源的宽高w,h,源资源的宽高w,h)
//                 imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'], $resWidth, $resHeight);
//                 //$val['left'] = $val['left']<0?$backgroundWidth- abs($val['left']) - $val['width']:$val['left'];
//                 //如果left小于-1我这做成了计算让其水平居中
//                 if ($val['left'] < 0) {
//                     $val['left'] = ceil($backgroundWidth - $val['width']) / 2;
//                 }
//                 $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) - $val['height'] : $val['top'];
//                 //放置图像
//                 imagecopymerge($imageRes, $canvas, $val['left'], $val['top'], $val['right'], $val['bottom'], $val['width'], $val['height'], $val['opacity']); //左,上,右,下,宽度,高度,透明度
                
//             }
//         }
//         //处理文字
//         if (!empty($config['text'])) {
//             foreach ($config['text'] as $key => $val) {
//                 $val = array_merge($textDefault, $val);
//                 list($R, $G, $B) = explode(',', $val['fontColor']);
//                 $fontColor = imagecolorallocate($imageRes, $R, $G, $B);
//                 //$val['left'] = $val['left']<0?$backgroundWidth- abs($val['left']):$val['left'];
//                 //如果left小于-1我这做成了计算让其水平居中
//                 if ($val['left'] < 0) {
//                     $fontBox = imagettfbbox($val['fontSize'], 0, $val['fontPath'], $val['text']); //文字水平居中实质
//                     $val['left'] = ceil(($backgroundWidth - $fontBox[2]) / 2); //计算文字的水平位置
                    
//                 }
//                 $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) : $val['top'];
//                 imagettftext($imageRes, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
//             }
//         }
//         //生成图片
//         if (!empty($filename)) {
//             $res = imagejpeg($imageRes, $filename, 90); //保存到本地
//             imagedestroy($imageRes);
//             if (!$res) return false;
//             return $filename;
//         } else {
//             header("Content-type:image/png");
//             imagejpeg($imageRes); //在浏览器上显示
//             imagedestroy($imageRes);
//         }
//     }
// }
方案二(参数动态配置)
php 复制代码
if(!function_exists('createInviteImg')){
    // 生成推广员邀请码图片
	function createInviteImg($promoter_code, $promoter_name, $promoter_code_id){ 
        $site = Config::get("site");

        // 邀请海报背景图       
        $inviteBgImg = isset($site['inviteBgImg'])&& $site['inviteBgImg'] ? $site['inviteBgImg'] : '/assets/img/inviteBgImg.png';
        // 二维码宽度px
        $codeWidth = isset($site['codeWidth'])&& $site['codeWidth'] ? $site['codeWidth'] : 284;
        // 二维码内边距px
        $codePadding = isset($site['codePadding'])&& $site['codePadding'] ? $site['codePadding'] : 7;
        // 二维码圆角px
        $codeRadius = isset($site['codeRadius'])&& $site['codeRadius'] ? $site['codeRadius'] : 20;
        // 二维码与海报顶部距离px
        $codeTop = isset($site['codeTop'])&& $site['codeTop'] ? $site['codeTop'] : 927;
        // 邀请码前缀
        $invatePrefix = isset($site['invatePrefix'])&& $site['invatePrefix'] ? $site['invatePrefix'] : '邀请码:';
        // 邀请码字号大小px
        $invateFontSize = isset($site['invateFontSize'])&& $site['invateFontSize'] ? $site['invateFontSize'] : 20;
        // 邀请码字体颜色
        $invateFontColor = isset($site['invateFontColor'])&& $site['invateFontColor'] ? $site['invateFontColor'] : '255,255,255';
        // 邀请码与海报顶部距离px
        $invateTop = isset($site['invateTop'])&& $site['invateTop'] ? $site['invateTop'] : 910;

        
        // 生成二维码
        $text = cdnurl("/promoter_invite?promoter_code=".$promoter_code,true); // 微信扫码跳转到小程序
        list($filePath,$fileUrl) = buildQrcode($text, '', '/uploads/qrcode/promoter/', 'code_'.$promoter_code_id.'_'.time(), $codeWidth, $codePadding, true, $codeRadius);
        
        // 生成邀请海报
        $fileUrl = '/uploads/qrcode/promoter/promoter_'. $promoter_code_id.'_'.time().'.jpg';
        $filename = ROOT_PATH .'public'. $fileUrl;
        $config = array(
            'image'=>array(
                array(
                    'url'=>$filePath,     //二维码地址
                    'stream'=>0,
                    'left'=>-1,               //小于0为小平居中                             
                    'top'=>$codeTop,
                    'right'=>0,
                    'width'=>$codeWidth,             //图像宽
                    'height'=>$codeWidth,            //图像高
                    'opacity'=>100,            //透明度
                ),
            ),
            'text'=>array(
                array(
                    'text'=>$invatePrefix.$promoter_code,            //文字内容
                    'left'=>-1,                              //小于0为水平居中      
                    'top'=>$invateTop,
                    'fontSize'=>$invateFontSize,                         //字号
                    'fontColor'=>$invateFontColor,                //字体颜色
                    'angle'=>0,
                    'fontPath'=>ROOT_PATH.'public/assets/fonts/msyh/msyh.ttf',     //字体文件
                )
            ),
            'background'=>ROOT_PATH.'public'.$inviteBgImg,          //背景图
            // 'background'=>cdnurl('/assets/img/haibao.png',true),          //背景图
        );

        //echo createPoster($config);
        //$filename为空是真接浏览器显示图片
        createPoster($config,$filename);
            
        // 删除二维码文件
        @unlink($filePath); 

        return $fileUrl;
        // return cdnurl($fileUrl,true);
    }

}


if (!function_exists('buildQrcode')) {
    // 生成二维码
    function buildQrcode($text, $label, $file_url, $name='', $width, $padding, $rounded=true, $radius = 20)
    {
        $params = [
            'text'           => $text,
            'size'           => $width,    //大小
            'padding'        => $padding,    //内边距
            'errorlevel'     => 'medium',   //容错级别:low-低   medium-中等   quartile-高   high-超高
            'foreground'     => "#000000",     //前景色
            'background'     => "#ffffff",  //背景色
            'logo'           => 0,    //Logo:1-显示,0-不显示
            'logosize'       => '',  //Logo大小
            'label'          => $label, //标签
            'labelfontsize'  => 16, //标签大小
            'labelalignment' => 'center',    //标签水平位置:left-左  center-中   right-右
        ];

        $qrCode = \addons\qrcode\library\Service::qrcode($params);

        $response = Response::create()->header("Content-Type", "image/png");

        // 直接显示二维码
        header('Content-Type: ' . $qrCode->getMimeType());
        $response->content($qrCode->getString());

        // 写入到文件
        $file_name = $name?$name:md5(implode('', $params));
        $fileUrl = $file_url . $file_name . '.png';
        $filePath = ROOT_PATH .'public'. $fileUrl;
        if (!file_exists(ROOT_PATH .'public/uploads/qrcode/')) mkdir (ROOT_PATH .'public/uploads/qrcode/',0777,true); 
        if (!file_exists(ROOT_PATH .'public'.$file_url)) mkdir (ROOT_PATH .'public'.$file_url,0777,true); 
        
        $qrCode->saveToFile($filePath);

        // 如果启用圆角,处理二维码图片
        if ($rounded) {
            $roundedFilePath = ROOT_PATH . 'public' . $file_url . $file_name . '_rounded.png';
            $roundedFileUrl = $file_url . $file_name . '_rounded.png';
            
            // 生成圆角二维码
            $result = applyRoundedCornersToImage($filePath, $roundedFilePath, $radius);
            
            if ($result) {
                @unlink($filePath);
                // 使用圆角二维码文件路径
                $filePath = $roundedFilePath;
                $fileUrl = $roundedFileUrl;
            }
        }

        return [$filePath,$fileUrl];
    }
}

/**
 * 给图片添加圆角
 * @param string $sourcePath 源图片路径
 * @param string $destPath 目标图片路径
 * @param int $radius 圆角半径
 * @return bool 是否成功
 */
function applyRoundedCornersToImage($sourcePath, $destPath, $radius = 20) {
    // 获取图片信息
    $info = getimagesize($sourcePath);
    if ($info === false) {
        return false;
    }
    
    // 根据图片类型创建图像资源
    $imageType = $info[2];
    switch ($imageType) {
        case IMAGETYPE_PNG:
            $sourceImage = imagecreatefrompng($sourcePath);
            break;
        case IMAGETYPE_JPEG:
            $sourceImage = imagecreatefromjpeg($sourcePath);
            break;
        case IMAGETYPE_GIF:
            $sourceImage = imagecreatefromgif($sourcePath);
            break;
        default:
            return false;
    }
    
    if (!$sourceImage) {
        return false;
    }
    
    $width = imagesx($sourceImage);
    $height = imagesy($sourceImage);
    
    // 创建新图像
    $roundedImage = imagecreatetruecolor($width, $height);
    
    // 设置透明背景
    imagealphablending($roundedImage, false);
    imagesavealpha($roundedImage, true);
    $transparent = imagecolorallocatealpha($roundedImage, 0, 0, 0, 127);
    imagefill($roundedImage, 0, 0, $transparent);
    
    // 创建圆角遮罩
    $mask = imagecreatetruecolor($width, $height);
    $white = imagecolorallocate($mask, 255, 255, 255);
    $black = imagecolorallocate($mask, 0, 0, 0);
    imagefill($mask, 0, 0, $white);
    
    // 绘制黑色圆角矩形(这是我们要保留的区域)
    drawRoundedRect($mask, 0, 0, $width, $height, $radius, $black);
    
    // 应用遮罩
    for ($x = 0; $x < $width; $x++) {
        for ($y = 0; $y < $height; $y++) {
            $maskColor = imagecolorat($mask, $x, $y);
            $maskRgb = imagecolorsforindex($mask, $maskColor);
            
            // 如果遮罩是黑色(在圆角矩形内),复制原图像素
            if ($maskRgb['red'] == 0 && $maskRgb['green'] == 0 && $maskRgb['blue'] == 0) {
                $srcColor = imagecolorat($sourceImage, $x, $y);
                $srcRgb = imagecolorsforindex($sourceImage, $srcColor);
                
                $newColor = imagecolorallocatealpha(
                    $roundedImage,
                    $srcRgb['red'],
                    $srcRgb['green'],
                    $srcRgb['blue'],
                    $srcRgb['alpha']
                );
                
                imagesetpixel($roundedImage, $x, $y, $newColor);
            }
        }
    }
    
    // 保存圆角图片
    imagepng($roundedImage, $destPath, 9);
    
    // 释放资源
    imagedestroy($sourceImage);
    imagedestroy($roundedImage);
    imagedestroy($mask);
    
    return true;
}

/**
 * 绘制圆角矩形
 */
function drawRoundedRect($image, $x, $y, $width, $height, $radius, $color) {
    // 确保半径不超过矩形的一半
    $radius = min($radius, floor($width / 2), floor($height / 2));
    
    // 绘制四个圆角
    imagefilledarc($image, $x + $radius, $y + $radius, $radius * 2, $radius * 2, 180, 270, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $width - $radius, $y + $radius, $radius * 2, $radius * 2, 270, 360, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $width - $radius, $y + $height - $radius, $radius * 2, $radius * 2, 0, 90, $color, IMG_ARC_PIE);
    imagefilledarc($image, $x + $radius, $y + $height - $radius, $radius * 2, $radius * 2, 90, 180, $color, IMG_ARC_PIE);
    
    // 绘制矩形部分
    imagefilledrectangle($image, $x + $radius, $y, $x + $width - $radius, $y + $radius, $color);
    imagefilledrectangle($image, $x, $y + $radius, $x + $radius, $y + $height - $radius, $color);
    imagefilledrectangle($image, $x + $radius, $y + $height - $radius, $x + $width - $radius, $y + $height, $color);
    imagefilledrectangle($image, $x + $width - $radius, $y + $radius, $x + $width, $y + $height - $radius, $color);
    
    // 填充中间区域
    imagefilledrectangle($image, $x + $radius, $y + $radius, $x + $width - $radius, $y + $height - $radius, $color);
}

if (!function_exists('createPoster')) {
    /**
     * 生成宣传海报(优化版,正确处理透明PNG)
     */
    function createPoster($config = array(), $filename = "") {
        if (empty($filename)) {
            header("content-type: image/png");
        }
        
        // 默认图片参数
        $imageDefault = array(
            'left' => 0,
            'top' => 0,
            'right' => 0,
            'bottom' => 0,
            'width' => 100,
            'height' => 100,
            'opacity' => 100
        );
        
        // 默认文字参数
        $textDefault = array(
            'text' => '',
            'left' => 0,
            'top' => 0,
            'fontSize' => 32,
            'fontColor' => '255,255,255',
            'angle' => 0,
        );
        
        // 加载背景图片
        $backgroundPath = $config['background'];
        if (!file_exists($backgroundPath)) {
            die('背景图片不存在: ' . $backgroundPath);
        }
        
        $background = imagecreatefromstring(file_get_contents($backgroundPath));
        if (!$background) {
            die('无法加载背景图片');
        }
        
        $backgroundWidth = imagesx($background);
        $backgroundHeight = imagesy($background);
        
        // 创建海报画布
        $poster = imagecreatetruecolor($backgroundWidth, $backgroundHeight);
        
        // 复制背景到海报
        imagecopy($poster, $background, 0, 0, 0, 0, $backgroundWidth, $backgroundHeight);
        
        // 处理图片元素
        if (!empty($config['image'])) {
            foreach ($config['image'] as $val) {
                $val = array_merge($imageDefault, $val);
                
                // 加载图片
                if (!file_exists($val['url'])) {
                    continue;
                }
                
                $imageContent = file_get_contents($val['url']);
                if (!$imageContent) {
                    continue;
                }
                
                $srcImage = imagecreatefromstring($imageContent);
                if (!$srcImage) {
                    continue;
                }
                
                $srcWidth = imagesx($srcImage);
                $srcHeight = imagesy($srcImage);
                
                // 创建临时画布
                $tempCanvas = imagecreatetruecolor($val['width'], $val['height']);
                
                // 设置透明背景
                imagesavealpha($tempCanvas, true);
                imagealphablending($tempCanvas, false);
                $transparent = imagecolorallocatealpha($tempCanvas, 0, 0, 0, 127);
                imagefill($tempCanvas, 0, 0, $transparent);
                
                // 重新采样图片
                imagecopyresampled($tempCanvas, $srcImage, 0, 0, 0, 0, $val['width'], $val['height'], $srcWidth, $srcHeight);
                
                // 计算位置
                if ($val['left'] < 0) {
                    $val['left'] = ceil(($backgroundWidth - $val['width']) / 2);
                }
                
                if ($val['top'] < 0) {
                    $val['top'] = ceil(($backgroundHeight - $val['height']) / 2);
                }
                
                // 合并到海报
                imagecopy($poster, $tempCanvas, $val['left'], $val['top'], 0, 0, $val['width'], $val['height']);
                
                imagedestroy($srcImage);
                imagedestroy($tempCanvas);
            }
        }
        
        // 处理文字
        if (!empty($config['text'])) {
            foreach ($config['text'] as $val) {
                $val = array_merge($textDefault, $val);
                
                // 设置字体颜色
                list($R, $G, $B) = explode(',', $val['fontColor']);
                $fontColor = imagecolorallocate($poster, $R, $G, $B);
                
                // 计算文字位置
                if ($val['left'] < 0) {
                    // 水平居中
                    $fontPath = isset($val['fontPath']) ? $val['fontPath'] : '';
                    if ($fontPath && file_exists($fontPath)) {
                        $bbox = imagettfbbox($val['fontSize'], $val['angle'], $fontPath, $val['text']);
                        if ($bbox) {
                            $textWidth = $bbox[2] - $bbox[0];
                            $val['left'] = ceil(($backgroundWidth - $textWidth) / 2);
                        }
                    }
                }
                
                // 添加文字
                if (isset($val['fontPath']) && file_exists($val['fontPath'])) {
                    imagettftext($poster, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
                }
            }
        }
        
        // 输出或保存图片
        if (!empty($filename)) {
            // 确保目录存在
            $dir = dirname($filename);
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
            
            // 保存为JPEG
            imagejpeg($poster, $filename, 90);
            imagedestroy($poster);
            imagedestroy($background);
            
            return file_exists($filename) ? $filename : false;
        } else {
            // 直接输出
            header('Content-Type: image/jpeg');
            imagejpeg($poster);
            imagedestroy($poster);
            imagedestroy($background);
            exit;
        }
    }
}

效果图示:

提前安装二维码生成插件
相关推荐
JSON_L1 天前
Fastadmin中使用GatewayClient
php·fastadmin
JSON_L1 天前
Fastadmin中使用百度翻译API
php·fastadmin·百度翻译api
行业探路者7 天前
2026年热销榜单:富媒体展示二维码推荐,助力信息传递新风尚
大数据·音视频·二维码
行业探路者14 天前
音频二维码让音频分享变得更简单快捷
学习·音视频·语音识别·二维码·设备巡检
JSON_L15 天前
Fastadmin Excel 导入实现
php·excel·fastadmin
JSON_L16 天前
PHP 获取国内ip归属地
开发语言·php·fastadmin
u13013021 天前
深入解析二维码技术与前端生成方案
前端·二维码
行业探路者22 天前
健康宣教二维码是什么?主要有哪些创新优势?
人工智能·学习·音视频·二维码·产品介绍
行业探路者22 天前
提升产品宣传效果的二维码应用新趋势
大数据·人工智能·学习·二维码·产品介绍