我的编程空间,编程开发者的网络收藏夹
学习永远不晚

php GD库为图片添加文字且自动换行,水平居中

短信预约 PHP-IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

php GD库为图片添加文字且自动换行,水平居中

本文可以帮助你解决一下问题:

1,GD库添加文字水印无法换行

2,GD库添加文本实现居中显示

3,stil/gd-text扩展包添加文字为中文时,换行失效

GD库是php处理图形的扩展库,GD库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片,也可以给图片加水印。我们常用它生成网址验证码,图片缩略图,分享海报等等。

一,前置条件

1,确保你的PHP安装了GD扩展,并在php.ini启用了该扩展
2,phpinfo()查看GD扩展已开启:

3,以下每段代码快最后三句均为调试代码,用以在浏览器查看当前图片。所有代码块连接在一起时,需要去除调试代码

二,创建一幅图片(画布)

//1,添加一个画布$img,同时给这个画布添加背景图片$bg

    $bgPath = './images/bg.jpg';
    $bgInfo = getimagesize($bgPath);
    $bgFun = 'imagecreatefrom'.image_type_to_extension($bgInfo[2], false);
    //创建一个图: 460*830
    $bg = $bgFun($bgPath);

    $bgWidth = imagesx($bg);  //背景宽度
    $bgHeight = imagesy($bg);  //背景高度

    $img = imageCreatetruecolor($bgWidth,$bgHeight);
    $color = imagecolorallocate($img, 0, 0, 0);
    imagefill($img, 0, 0, $color);

    //平滑的拷贝背景图到$img
    imagecopyresampled($img,$bg,0,0,0,0,imagesx($bg),imagesy($bg),imagesx($bg),imagesy($bg));

    //打印查看:
    header('Content-Type: image/png;charset=UTF-8');//必须声明
    imagepng($img);
    exit;

三,为图片添加水印

//2,使用GD库在一张图片上面加文字:

   $font = realpath("./font/simhei.ttf");
   //显示的文字
   $text = "A class drawing multiline and aligned text on pictures";
   //设置字体颜色
   $black = imagecolorallocate($img, 65, 65, 65);
   //将ttf文字写到图片中
   imagettftext($img, 16, 0, 52, 170, $black, $font, $text);

   //打印查看:
   header('Content-Type: image/png;charset=UTF-8');//必须声明
   imagepng($img);
   exit;

可以看到,当文本超长时,直接被截断了,超出图片宽度的文字直接不可见。事实上,使用GD库为图片添加文字水印,它是不处理文本长度的。我们可以理解GD库只处理图片有多少个像素组成,图片长宽多少,每一个像素点A(x,y)是什么颜色。
但是我们动态生成的图片,不确定性太多,例如用户昵称,用户签名,商品名称等等这些长度都不确定,造成了我们生成的图片的文本长度不确定,如果文本超出了,那么我们需要怎样去处理超长的文本呢?
答案是,自己去处理,通过自己设置的字体大小,图片的宽度,计算出多少个字之后,就会被截断,在截断之前自己生成新的字符串写在第二行上面。
关键函数:

$box = imagettfbbox ( 20, 0,$font, $ccv );
根据 $box 提供的信息适当裁剪 $ccv 使之可以放下

四,stil/gd-text的引入

但是人生苦短,研究技术的小伙伴可以自己去搞一搞,但是打工人时间紧任务重,gd-text这个包已经帮我们封装好了我们想要的东西,就不建议重复造轮子了,我们直接使用。
它的使用方法类似于我们在PPT上面添加一个文本框一样:给它一个左上角坐标A(x,y),宽度,高度。一个文本框就形成了,那我们在这个框里面写东西,超出的文字就会自动换行。是不是非常方便
1,安装:使用composer安装:

composer require stil/gd-text

2,使用:

<?php
require __DIR__.'./vendor/autoload.php';
use GDText\Box;
use GDText\Color;

//1,添加一个画布$img,同时给这个画布添加背景图片$bg

    $bgPath = './images/bg.jpg';
    $bgInfo = getimagesize($bgPath);
    $bgFun = 'imagecreatefrom'.image_type_to_extension($bgInfo[2], false);
    //创建一个图: 460*830
    $bg = $bgFun($bgPath);
    $bgWidth = imagesx($bg);  //背景宽度
    $bgHeight = imagesy($bg);  //背景高度

    $img = imageCreatetruecolor($bgWidth,$bgHeight);
    $color = imagecolorallocate($img, 0, 0, 0);
    imagefill($img, 0, 0, $color);

    //平滑的拷贝背景图到$img
    imagecopyresampled($img,$bg,0,0,0,0,imagesx($bg),imagesy($bg),imagesx($bg),imagesy($bg));


//3,使用gd-text包来为图片添加文字:

    $box = new Box($img);
    $font = realpath("./font/simhei.ttf");
    //显示的文字
    $text = "A class drawing multiline and aligned text on pictures";
    $box->setFontFace($font);
    $box->setFontColor(new Color(77, 77, 77));//字体颜色
    $box->setFontSize(18);//字体大小
    $box->setLineHeight(1.5);//行高
   
    //下面为关键函数:画一个文本框:
    $box->setBox(52, 200, 370, 200);//文本框起始点(x,y),长宽
    //第一个参数设置水平:靠左-left,居中-center,靠右-right;第二个参数设置垂直:靠左-left,居中-center,靠右-right
    $box->setTextAlign('left', 'top');
    $box->draw($text);

    //再画一个,这个是水平居中对齐的文本框:
    $box->setBox(52, 380, 370, 200);
    $box->setTextAlign('center', 'top');
    $box->draw($text);

    //打印查看:
    header('Content-Type: image/png;charset=UTF-8');//必须声明
    imagepng($img);
    exit;

3,可以看到非常方便,但是当我们的传入的文本为中文时,奇怪的事情发生了,它并不能自动换行???(手动黑人问号脸)。网上没啥资料,自己看源代码了。

五,修改源代码

通过查看gd-text包的源码,我们可以发现,它是在class="lazy" data-src/Box.php里面的wrapTextWithOverflow()方法实现换行的。原来,当文本填满第一行时,它是通过空格拆分一串字符的,这很好理解,例如我们第一行八个单词排上去,还差3个字母,就要填满第一行了,而第九个单词(International)有13个字母,按照惯例我们不会把这个单词的前3个字母给拆掉的,而是整个单词都写在第二行去。所有,它内部是用explode()这个函数根据空格去拆单词,然后逐个计算在那里换行的。
但是我们的中文并不是每个字后面都有空格,explode()函数分隔符为必传,那怎么办呢?

1,自己在每个字后面加1个空格,这样就能自动换行。但是这样字距很大,并不美观。
2,str_split(string,length)函数,它可以分割字符串,第二个参数为分割后每个字符的长度。

但是分完后你会发现全是是乱码,因为中文一个字占三个字节,英文字母占一个字节;
那我当要插入中文的时候,用str_split(string,3)不就好了吗?当插入英文,就用explode();完美!
并不,很多时候我们都不敢保证一段就一定是英文或者是中文,它还有可能中文夹杂着英文,那这时候,依然是乱码。
这时候,还有其他办法吗?有,我们用强大的正则表达式

3,使用正则表达式

这个方法可以真正完全解决问题,下面我们开始修改源代码:
事实上我们是不建议直接改扩展包里面的源码的,这样不规范,但是现在先略过
1,在class="lazy" data-src/Box.php里面添加一个方法:

    
    protected function mb_str_split($str){
        return preg_split('/(?<!^)(?!$)/u', $str );
    }

2,修改wrapTextWithOverflow()方法,加多一个参数,用来判断用那种方法截取字符串:英文文本用空格;中文、中英混合文本用正则

    
    protected function wrapTextWithOverflow($text,$isChinese = false)
    {
        $lines = array();
        // Split text explicitly into lines by \n, \r\n and \r
        $explicitLines = preg_split('/\n|\r\n?/', $text);
        foreach ($explicitLines as $line) {
            // Check every line if it needs to be wrapped
            if($isChinese){
                $words = $this->mb_str_split($line);
            }else{
                $words = explode(" ", $line);
            }
            $line = $words[0];
            for ($i = 1; $i < count($words); $i++) {
                $box = $this->calculateBox($line." ".$words[$i]);
                if (($box[4]-$box[6]) >= $this->box['width']) {
                    $lines[] = $line;
                    $line = $words[$i];
                } else {
                    $line .= $words[$i];
                }
            }
            $lines[] = $line;
        }
        return $lines;
    }

3,修改draw()方法,加多一个参数,用来判断用那种方法截取字符串:英文文本用空格;中文、中英混合文本用正则


    public function draw($text,$isChinese = false)
    {
        if (!isset($this->fontFace)) {
            throw new \InvalidArgumentException('No path to font file has been specified.');
        }

        switch ($this->textWrapping) {
            case TextWrapping::NoWrap:
                $lines = array($text);
                break;
            case TextWrapping::WrapWithOverflow:
            default:
                $lines = $this->wrapTextWithOverflow($text,$isChinese);
                break;
        }

        //只改上面这几行,该方法下面的代码维持不变

4,使用draw()方法的时候,遇到中文文本,我们第二个参数传true就可以了。

//4,使用gd-text包来添加一段中文文本:
    $text2 = '你好,世界,学无止境。你好,世界,学无止境。你好,世界,学无止境。你好,世界,学无止境。你好,世界,学无止境。';
    $box->setBox(52, 550, 370, 200);
    $box->setTextAlign('left', 'top');
    $box->draw($text2,true);

至此,使用GD库为图片添加文字且自动换行的分享到此结束,希望对你有所帮助

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

php GD库为图片添加文字且自动换行,水平居中

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

php GD库为图片添加文字且自动换行,水平居中

本文可以帮助你解决一下问题:1,GD库添加文字水印无法换行2,GD库添加文本实现居中显示3,stil/gd-text扩展包添加文字为中文时,换行失效GD库是php处理图形的扩展库,GD库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片,也可以给图片加水印。我们常用它生成网址验证码,图片缩略图,分享
php GD库为图片添加文字且自动换行,水平居中
2024-04-02

编程热搜

  • Python代码加密思路与实现
    前言公司开发了一套储能相关的诊断与预测算法,交付第三方使用时,考虑到算法泄漏的问题,需要对算法进行加密对于动态语言来说,代码混淆是最常见的方式;针对于python,还可以使用cython将代码构建成动态链接库。项目使用的FastAPI框架代码混淆代码混淆作为加密并不是很好的选择,在使用开源工具测试后,放弃了这种方式,主
    Python代码加密思路与实现
  • PHP 8.3 大升级:20 个新特性全面解析
    PHP 8.3 是流行的服务器端脚本语言的最新版本,带来了许多新功能和改进,旨在简化 Web 开发并提高性能。这些增强功能包括只读类、新函数 json_validate() 、Randomizer 类的扩展以及更合适的日期/时间异常。它们将彻底改变 PHP 开发体验,使其更加高效、安全,以满足 Web 开发人员和企业的
    PHP 8.3 大升级:20 个新特性全面解析
  • PHP抓取抖音直播弹幕实操代码
    最近需要抓取抖音直播的弹幕消息,网上找了一下基本上都是 python 的版本,虽然用起来没有太大的影响,但本着 PHP 是世界上最好的语言 就写了一个简单的脚本方便使用。以下是主要代码:首先通过直播链接获取 ttwid$client = new Client();&nb
    PHP抓取抖音直播弹幕实操代码
  • Laravel 8 配合 Vuejs 实现单页面应用(SPA)
    我们都知道,Laravel 是一个很赞的框架!它允许全栈工程师们一站式构建前后端网站。因此,我们可以快速构建、交付高质量且安全的 web 项目。但它的强大不止于此。Laravel 还有很多事情可供探索发现。举个栗子,我们已经编写了一系列 Vue JS 的组件,这些组件可被嵌入到 Laravel 的页面中,动态的给用户提
    Laravel 8 配合 Vuejs 实现单页面应用(SPA)
  • github、gitlab等常用api
     注意: api地址区分大小写,github偶尔访问不了不要着急,耐心等待一会儿就好功能api地址请求方式请求参数返回参数例子获取用户信息 https://api.github.com/users/getpath路径: 用户名一个用户对象https://api.github.co
    github、gitlab等常用api
  • Laravel 编码技巧 - 邮件
    测试电子邮件到 laravel.log如果你想在应用中测试电子邮件内容,但又不想或无法设置像 Mailgun 这样的服务,可以使用 .env 参数 MAIL_DRIVER=log,所有的电子邮件将被保存到 storage/logs/laravel.log 文件中,而不是实际发送。在 Laravel 中,您无需将文件存储
    Laravel 编码技巧 - 邮件
  • Go 基础数据类型 - 布尔类型
    在 Go 语言中,使用关键字 bool 来声明布尔类型。布尔类型的值只能是 true 或 false,如 var flag bool = true。声明布尔类型布尔类型的声明有多种方式,下面直接看看案例。package mainimport "fmt"func main
    Go 基础数据类型 - 布尔类型
  • 如何在上班时间利用终端控制台摸鱼
    作为一个资深的摸鱼小能手,班我们每天要上,终端也是我们也要每天要用到的,那么有什么办法可以在控制台终端中去摸鱼呢,那么在接下来的文章中我们就来看看它可以做到怎么样摸鱼。简介在我们开发的项目中,几乎有很多项目要都是使用 webpack 作为构建工具来进行开发的,在它进行构建的时候,会有一些信息会输出在控制台上面,如下图所
    如何在上班时间利用终端控制台摸鱼
  • SpringBoot项目鉴权的4种方式小结
    文章介绍了spring-boot中实现通用auth的四种方式,包括 传统AOP、拦截器、参数解析器和过滤器,并提供了对应的实例代码,最后简单总结了下他们的执行顺序。前言最近一直被无尽的业务需求淹没,没时间喘息,终于接到一个能让我突破代码舒适区的活儿,解决它的过程非常曲折,一度让我怀疑人生,不过收获也很大,代码方面不明显
    SpringBoot项目鉴权的4种方式小结
  • 使用Composer从零开发一个简单的web框架(08)-monolog
    安装依赖pwd/d/apps/wamp/www/phpwebcomposer require monolog/monologUsing version ^3.5 for monolog/monolog./composer.json has 
    使用Composer从零开发一个简单的web框架(08)-monolog

目录