PHP 图像加入文字水印的自动换行解决方案(支持中文)

原文来源: https://blog.gxxsite.com/php-image-draw-text-line-auto-cut/

PHP 图像加入文字水印的自动换行解决方案(支持中文)

GD 库提供了大量的图片处理函数,其中书写文字也包含在里面,可是换行不属于绘画范畴,是一个需要自行解决的问题,这里记录我所用的解决方案

思路
根据字符的宽度和提供的宽度,计算出范围内每行可写多少个字符,用字符截取的方式把字符分割成数组,再分别绘制

所用到的函数:

getimagesize
imagecreatefromjpeg
imagecreatefrompng
imagefill
imagecopyresampled
imagejpeg
imagecolorallocate
imagettfbbox
imagettftext
分割函数

/*
 * 绘图文字分行函数
 * by COoL
 * - 输入:
 * str: 原字符串
 * fontFamily: 字体
 * fontSize: 字号
 * charset: 字符编码
 * width: 限制每行宽度(px)
 * - 输出:
 * 分行后的字符串数组
 */
function autoLineSplit ($str, $fontFamily, $fontSize, $charset, $width) {
    $result = [];

    $len = (strlen($str) + mb_strlen($str, $charset)) / 2;

    // 计算总占宽
    $dimensions = imagettfbbox($fontSize, 0, $fontFamily, $str);
    $textWidth = abs($dimensions[4] - $dimensions[0]);

    // 计算每个字符的长度
    $singleW = $textWidth / $len;
    // 计算每行最多容纳多少个字符
    $maxCount = floor($width / $singleW);

    while ($len > $maxCount) {
        // 成功取得一行
        $result[] = mb_strimwidth($str, 0, $maxCount, '', $charset);
        // 移除上一行的字符
        $str = str_replace($result[count($result) - 1], '', $str);
        // 重新计算长度
        $len = (strlen($str) + mb_strlen($str, $charset)) / 2;
    }
    // 最后一行在循环结束时执行
    $result[] = $str;
    
    return $result;
}

实例

$content = '诸菩萨摩诃萨应如是降伏其心!所有一切众生之类:若卵生、若胎生、若湿生、若化生;若有色、若无色;若有想、若无想、若非有想非无想,我皆令入无余涅盘而灭度之。如是灭度无量无数无边众生,实无众生得灭度者。何以故?须菩提!若菩萨有我相、人相、众生相、寿者相,即非菩萨。';

$bg = imagecreatefromjpeg('o.jpg');

$fontFamily = 'FZLTHJW.TTF';
$fontSize = 24;
$charset = 'utf8';
$textcolor = imagecolorallocate($bg, 0, 0, 0);
$lineHeight = 50;
$startX = 15;
$startY = 50;

$lineWidth = imagesx($bg) - $startX - $startY;

$lineArr = autoLineSplit($content, $fontFamily, $fontSize, $charset, $lineWidth);

foreach ($lineArr as $k => $v) {
    imagettftext($bg, $fontSize, 0, $startX, ($startY + ($lineHeight * $k)), $textcolor, $fontFamily, $v);
}

$fileName = date('YmdHis').rand(10000,100000).'.jpg';
$localUrl = '/upload/'.$fileName;

imagejpeg($bg, $localUrl, 90);

注意
若需求是不把文字写在图片上的话,就需要根据字符的总行数再新建一个高度适合的图像,填充背景色,再把原图绘制到新图上,最后把字符从原图高度加上一定的margin以后开始绘制(这里我就忽略了,就当抛砖引玉吧)
大多数字体,中英文的宽度并不是1:2,甚至不同字母的宽度不同,这就需要每一行都计算一次宽度,再进行截取,而不是我所写的用“总长/字符数”来简单计算每字符占位
需要注意Y轴开始点,默认是把Y作为字符中轴线绘制的。绘制图像是需要很精确的,在编写代码的时候不能马虎,调整不可能一步到位,需要耐心

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值