php生成海报优化版,php生成商品海报分享图,这个是背景透明的PNG格式!之前分享的是jpg的白色背景
用php的GD库生成海报是很常用的,比如给设计好的海报背景动态更换二维码、文本内容,生成商品分享导购图等。 这个类是给要生成PNG格式透明背景的人用的,根据自己的需求调整就行了。
效果如下(方便查看我下载后截图的,浏览器背景是白色不好体现);
实现代码如下:
class PosterPng
{
//图片质量,0~9
private $quality = 9;
//字体路径
//private static $font_path = 'C:/Windows/Fonts/simfang.ttf';
private $font_path = '';
//背景图片
private $backgroud_img = '';
//二维码/水印图片
private $code_img = '';
public function __construct($config = [])
{
if (!empty($config['font_path'])) {
$this->font_path = $config['font_path'];
}
if (!empty($config['backgroud_img'])) {
$this->backgroud_img = $config['backgroud_img'];
}
if (!empty($config['code_img'])) {
$this->code_img = $config['code_img'];
}
}
/**
* 开始制作
* 一个原则:在某张背景图上面添加图片、文字等
* @param $data
* @return mixed
*/
public function start($data)
{
if (!empty($data['quality'])) {
$this->quality = $data['quality'];
}
if (!empty($data['qrcode'])) {
$this->code_img = $data['qrcode'];
}
if (!empty($data['bg_img'])) {
$this->backgroud_img = $data['bg_img'];
}
//输入文件的路径和名称
$output_file = $data['output_file'];
//商品图片
$goods_img = $data['goods_img'];
if (empty($this->backgroud_img)) {
$bgH = 700;
$bgW = 375;
$image = imagecreatetruecolor($bgW, $bgH);
$transparent = imagecolorallocatealpha($image, 0, 0, 0, 127); // 创建透明颜色
imagealphablending($image, false); // 关闭混合模式
imagesavealpha($image, true); // 保存透明通道
imagefill($image, 0, 0, $transparent);
imagepng($image, $output_file); // 保存为 PNG 格式,以保留透明通道
imagedestroy($image);
$this->backgroud_img = $output_file;
// 添加二维码
$this->addPic($this->backgroud_img, $this->code_img, 100, 100, 275, 400, $output_file);
// 添加文字描述
$this->addWord('长按识别', 280, 522, 16, 'grey1', $output_file);
}
// 添加产品
$this->addPic($this->backgroud_img, $goods_img, 375, 400, 0, 0, $output_file);
// 添加产品描述,对描述进行分行
$theTitle = $this->cn_row_substr($data['title'], 2, 11);
//左右距离
$this->addWord($theTitle[1], 10, 425, 16, 'black', $output_file);
$this->addWord($theTitle[2], 10, 450, 16, 'black', $output_file);
// 文字1
$this->addWord('原价' . $data['price_member'], 20, 480, 16, 'black', $output_file);
// 文字2
$this->addWord('————', 65, 480, 16, 'red', $output_file);
$this->addWord('————', 65, 481, 16, 'red', $output_file);
$this->addWord('————', 65, 482, 16, 'red', $output_file);
// 文字3
$this->addWord('现价' . $data['price_market'], 20, 510, 18, 'red', $output_file);
//商品小图 todo 动态化来自$data 数组
if (!empty($data['imgs'])) {
$w = $h = 100;//小图宽高
$dst_y = 538;//距离海报顶部的距离
$margin_left = 20;//左边距
foreach ($data['imgs'] as $k => $thumb) {
//计算x轴坐标
if ($k == 0) {
$dst_x = $margin_left;
} else {
$dst_x = ($k + 1) * $margin_left + $w * $k;
}
//只取3张
if ($k >= 3) {
break;
}
//添加小图
$this->addPic($output_file, $thumb, $w, $h, $dst_x, $dst_y, $output_file);
}
}
// 文字3
$this->addWord('一个有血性的程序猿520单身快乐', 10, 670, 16, 'black', $output_file);
return $output_file;
}
/**
* 添加图片
* @param $path_base string 原图
* @param $path_logo string 添加图
* @param $imgWidth int 添加图宽
* @param $imgHeight int 添加图高
* @param $dst_x int 在原图宽x处添加
* @param $dst_y int 在原图高y处添加
* @param $output_file string 生成图
* return resource 返回图片image资源
*/
private function addPic($path_base, $path_logo, $imgWidth, $imgHeight, $dst_x, $dst_y, $output_file)
{
if (empty($path_logo)) {
exit('图片不存在:' . $path_logo);
} elseif (empty($path_base)) {
exit('背景图不存在:' . $path_base);
}
$image_base = $this->ImgInfo($path_base);
$image_logo = $this->ImgInfo($path_logo);
//重采样拷贝部分图像并调整大小
imagecopyresampled($image_base, $image_logo, $dst_x, $dst_y, 0, 0, $imgWidth, $imgHeight, imagesx($image_logo), imagesy($image_logo));
$bgWidth = imagesx($image_base);
$bgHeight = imagesy($image_base);
$merged_image = imagecreatetruecolor($bgWidth, $bgHeight);
$transparent = imagecolorallocatealpha($merged_image, 0, 0, 0, 127); // 创建透明颜色
imagealphablending($merged_image, false); // 关闭混合模式
imagesavealpha($merged_image, true); // 保存透明通道
imagefill($merged_image, 0, 0, $transparent);
imagecopyresampled($merged_image, $image_base, 0, 0, 0, 0, $bgWidth, $bgHeight, $bgWidth, $bgHeight);
imagecopyresampled($merged_image, $image_logo, $dst_x, $dst_y, 0, 0, $imgWidth, $imgHeight, imagesx($image_logo), imagesy($image_logo));
// 生成一个合并后的新图
imagepng($merged_image, $output_file); // 保存为 PNG 格式,以保留透明通道
imagedestroy($merged_image);
}
/**
* 从图片文件创建Image资源
* @param $img string 图片文件,支持url
* @return bool|resource 成功返回图片image资源,失败返回false
*/
private function ImgInfo($img)
{
if (is_resource($img)) {
return $img;
} elseif (preg_match('/http(s)?:///', $img)) {
$fileSuffix = $this->getNetworkImgType($img);
} else {
$fileSuffix = pathinfo($img, PATHINFO_EXTENSION);
}
if (!$fileSuffix) {
return false;
}
switch ($fileSuffix) {
case 'jpeg':
case 'jpg':
$theImage = @imagecreatefromjpeg($img);
break;
case 'png':
$theImage = imagecreatefromstring(file_get_contents($img));
//imagecreatefrompng($img);
break;
case 'gif':
$theImage = @imagecreatefromgif($img);
break;
default:
$theImage = @imagecreatefromstring(file_get_contents($img));
break;
}
return $theImage;
}
/**
* 获取网络图片类型
* @param $url string 网络图片url,支持不带后缀名url
* @return bool
*/
private function getNetworkImgType($url)
{
$ch = curl_init(); //初始化curl
curl_setopt($ch, CURLOPT_URL, $url); //设置需要获取的URL
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //支持https
curl_exec($ch);//执行curl会话
$http_code = curl_getinfo($ch);//获取curl连接资源句柄信息
curl_close($ch);//关闭资源连接
if ($http_code['http_code'] == 200) {
$theImgType = explode('/', $http_code['content_type']);
if ($theImgType[0] == 'image') {
return $theImgType[1];
} else {
return false;
}
} else {
return false;
}
}
/**
* 分行连续截取字符串
* @param $str string 需要截取的字符串,UTF-8
* @param int $row 截取的行数
* @param int $number 每行截取的字数,中文长度
* @param bool $suffix 最后行是否添加‘...’后缀
* @return array 返回数组共$row个元素,下标1到$row
*/
private function cn_row_substr($str, $row = 1, $number = 10, $suffix = true)
{
$result = array();
for ($r = 1; $r <= $row; $r++) {
$result[$r] = '';
}
$str = trim($str);
if (!$str) return $result;
$theStrlen = strlen($str);
//每行实际字节长度
$oneRowNum = $number * 3;
for ($r = 1; $r <= $row; $r++) {
if ($r == $row and $theStrlen > $r * $oneRowNum and $suffix) {
$result[$r] = $this->mg_cn_substr($str, $oneRowNum - 6, ($r - 1) * $oneRowNum) . '...';
} else {
$result[$r] = $this->mg_cn_substr($str, $oneRowNum, ($r - 1) * $oneRowNum);
}
if ($theStrlen < $r * $oneRowNum) break;
}
return $result;
}
/**
* 按字节截取utf-8字符串
* 识别汉字全角符号,全角中文3个字节,半角英文1个字节
* @param $str string 需要切取的字符串
* @param $len int 截取长度[字节]
* @param int $start 截取开始位置,默认0
* @return string
*/
private function mg_cn_substr($str, $len, $start = 0)
{
$q_str = '';
$q_strlen = ($start + $len) > strlen($str) ? strlen($str) : ($start + $len);
//如果start不为起始位置,若起始位置为乱码就按照UTF-8编码获取新start
if ($start and json_encode(substr($str, $start, 1)) === false) {
for ($a = 0; $a < 3; $a++) {
$new_start = $start + $a;
$m_str = substr($str, $new_start, 3);
if (json_encode($m_str) !== false) {
$start = $new_start;
break;
}
}
}
//切取内容
for ($i = $start; $i < $q_strlen; $i++) {
//ord()函数取得substr()的第一个字符的ASCII码,如果大于0xa0的话则是中文字符
if (ord(substr($str, $i, 1)) > 0xa0) {
$q_str .= substr($str, $i, 3);
$i += 2;
} else {
$q_str .= substr($str, $i, 1);
}
}
return $q_str;
}
private function addWord($str, $posX, $poxY, $font, $color, $output_file, $tilt = 0)
{
$ori_img = $output_file; //原图
$new_img = $output_file; //生成水印后的图片
$s_original = $this->ImgInfo($ori_img);
imagealphablending($s_original, false); // 关闭混合模式
imagesavealpha($s_original, true); // 保存透明通道
$ImgColor = [
//为一幅图像分配颜色
'black' => imagecolorallocate($s_original, 0, 0, 0),
'red' => imagecolorallocate($s_original, 255, 0, 0),
'grey1' => imagecolorallocate($s_original, 31, 31, 18),
];
imagettftext($s_original, $font, $tilt, $posX, $poxY, $ImgColor[$color], $this->font_path, $str);
imagepng($s_original, $new_img, $this->quality);
imagedestroy($s_original);
}
}
调用也是很简单的,实例化入参即可:
<?php
//引入类库
require("PosterPng.php");
//定义入参
$img = 'abc.png';
$data = [
'title' => '一个不算长得不算太丑有信仰的代码写手...',
'price_market' => '¥0.99',
'price_member' => '¥99.99',
'goods_img' => 'https://store.mp.video.tencent-cloud.com/161/20304/snscosdownload/SH/reserved/6066d1500000815100000000b61f9d09000000a000004f50',
'output_file' => __DIR__ . '/'.$img,
'quality' => 9,
'qrcode' => __DIR__ . '/qr.png',
//'bg_img' => __DIR__.'/bg1.png',
'imgs' => [
__DIR__ . '/goods.jpeg',
__DIR__ . '/goods.jpeg',
__DIR__ . '/goods.jpeg',
]
];
//注意哈
$set = [
'font_path' => __DIR__ . '/simkai.ttf',
];
$poster = new PosterPng($set);
$newImg = $poster->start($data);
echo "<img style='width: 100%' src='{$img}' />";
注意事项: ①字体路径; ②字体模糊的问题处理; ③目录权限; ④其他优化
核心:
$transparent = imagecolorallocatealpha($image, 0, 0, 0, 127); // 创建透明颜色
imagealphablending($image, false); // 关闭混合模式
imagesavealpha($image, true); // 保存透明通道
imagefill($image, 0, 0, $transparent);
imagepng($image, $output_file); // 保存为 PNG 格式,以保留透明通道
上面是核心的内容,创建透明的和保存也是透明的即可
发现背景变成黑色不要慌,总不比我的生活那么灰暗的,黑色背景大都是没有用png生成模式、没有用alpha模式,对照下药就行了,addPic和addWord两个方法里面有:
imagealphablending($s_original, false); // 关闭混合模式
imagesavealpha($s_original, true); // 保存透明通道
最后,祝大家身体健康、天天开心、家庭美满、好事连连。
转载自:https://juejin.cn/post/7236286358389456954