php GD庫為圖片添加文字且自動換行曹货,水平居中

本文可以幫助你解決一下問題:

1咆繁,GD庫添加文字水印無法換行
2讳推,GD庫添加文本實現(xiàn)居中顯示
3,stil/gd-text擴展包添加文字為中文時么介,換行失效

GD庫是php處理圖形的擴展庫娜遵,GD庫提供了一系列用來處理圖片的API,使用GD庫可以處理圖片壤短,或者生成圖片设拟,也可以給圖片加水印。我們常用它生成網(wǎng)址驗證碼久脯,圖片縮略圖纳胧,分享海報等等。

一帘撰,前置條件

1跑慕,確保你的PHP安裝了GD擴展,并在php.ini啟用了該擴展
2摧找,phpinfo()查看GD擴展已開啟:


image.png

3核行,以下每段代碼快最后三句均為調(diào)試代碼,用以在瀏覽器查看當(dāng)前圖片蹬耘。所有代碼塊連接在一起時芝雪,需要去除調(diào)試代碼

二,創(chuàng)建一幅圖片(畫布)

//1综苔,添加一個畫布$img惩系,同時給這個畫布添加背景圖片$bg

    $bgPath = './images/bg.jpg';
    $bgInfo = getimagesize($bgPath);
    $bgFun = 'imagecreatefrom'.image_type_to_extension($bgInfo[2], false);
    //創(chuàng)建一個圖: 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";
   //設(shè)置字體顏色
   $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;
image.png

可以看到堡牡,當(dāng)文本超長時,直接被截斷了杨刨,超出圖片寬度的文字直接不可見晤柄。事實上崩溪,使用GD庫為圖片添加文字水印吉捶,它是不處理文本長度的。我們可以理解GD庫只處理圖片有多少個像素組成龙优,圖片長寬多少做粤,每一個像素點A(x,y)是什么顏色。
但是我們動態(tài)生成的圖片捉撮,不確定性太多怕品,例如用戶昵稱,用戶簽名巾遭,商品名稱等等這些長度都不確定肉康,造成了我們生成的圖片的文本長度不確定闯估,如果文本超出了,那么我們需要怎樣去處理超長的文本呢吼和?
答案是涨薪,自己去處理,通過自己設(shè)置的字體大小炫乓,圖片的寬度刚夺,計算出多少個字之后,就會被截斷末捣,在截斷之前自己生成新的字符串寫在第二行上面侠姑。
關(guān)鍵函數(shù):

$box = imagettfbbox ( 20, 0,$font, $ccv );
根據(jù) $box 提供的信息適當(dāng)裁剪 $ccv 使之可以放下

四,stil/gd-text的引入

但是人生苦短箩做,研究技術(shù)的小伙伴可以自己去搞一搞莽红,但是打工人時間緊任務(wù)重,gd-text這個包已經(jīng)幫我們封裝好了我們想要的東西邦邦,就不建議重復(fù)造輪子了安吁,我們直接使用。
它的使用方法類似于我們在PPT上面添加一個文本框一樣:給它一個左上角坐標(biāo)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);
    //創(chuàng)建一個圖: 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);//行高
   
    //下面為關(guān)鍵函數(shù):畫一個文本框:
    $box->setBox(52, 200, 370, 200);//文本框起始點(x,y),長寬
    //第一個參數(shù)設(shè)置水平:靠左-left豁状,居中-center捉偏,靠右-right;第二個參數(shù)設(shè)置垂直:靠左-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;
image.png

3谊路,可以看到非常方便讹躯,但是當(dāng)我們的傳入的文本為中文時,奇怪的事情發(fā)生了,它并不能自動換行潮梯?骗灶??(手動黑人問號臉)秉馏。網(wǎng)上沒啥資料耙旦,自己看源代碼了。

五萝究,修改源代碼

通過查看gd-text包的源碼免都,我們可以發(fā)現(xiàn),它是在src/Box.php里面的wrapTextWithOverflow()方法實現(xiàn)換行的糊肤。原來琴昆,當(dāng)文本填滿第一行時,它是通過空格拆分一串字符的馆揉,這很好理解业舍,例如我們第一行八個單詞排上去,還差3個字母升酣,就要填滿第一行了舷暮,而第九個單詞(International)有13個字母,按照慣例我們不會把這個單詞的前3個字母給拆掉的噩茄,而是整個單詞都寫在第二行去下面。所有,它內(nèi)部是用explode()這個函數(shù)根據(jù)空格去拆單詞绩聘,然后逐個計算在那里換行的沥割。
但是我們的中文并不是每個字后面都有空格,explode()函數(shù)分隔符為必傳凿菩,那怎么辦呢机杜?

1,自己在每個字后面加1個空格衅谷,這樣就能自動換行椒拗。但是這樣字距很大,并不美觀获黔。
2蚀苛,str_split(string,length)函數(shù),它可以分割字符串玷氏,第二個參數(shù)為分割后每個字符的長度堵未。

但是分完后你會發(fā)現(xiàn)全是是亂碼,因為中文一個字占三個字節(jié)盏触,英文字母占一個字節(jié)渗蟹;
那我當(dāng)要插入中文的時候侦厚,用str_split(string,3)不就好了嗎?當(dāng)插入英文拙徽,就用explode();完美诗宣!
并不膘怕,很多時候我們都不敢保證一段就一定是英文或者是中文,它還有可能中文夾雜著英文召庞,那這時候岛心,依然是亂碼。
這時候篮灼,還有其他辦法嗎忘古?有,我們用強大的正則表達式

3诅诱,使用正則表達式

這個方法可以真正完全解決問題髓堪,下面我們開始修改源代碼:
事實上我們是不建議直接改擴展包里面的源碼的,這樣不規(guī)范娘荡,但是現(xiàn)在先略過
1干旁,在src/Box.php里面添加一個方法:

    /**
     * 拆分字符串為數(shù)組
     * @param $str
     * @author shaochao 2021/3/23 21:22
     * @return  array|false|string[]
     */
    protected function mb_str_split($str){
        return preg_split('/(?<!^)(?!$)/u', $str );
    }

2,修改wrapTextWithOverflow()方法,加多一個參數(shù)炮沐,用來判斷用那種方法截取字符串:英文文本用空格争群;中文、中英混合文本用正則

    /**
     * Splits overflowing text into array of strings.
     * @param string $text
     * @return string[]
     */
    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()方法换薄,加多一個參數(shù),用來判斷用那種方法截取字符串:英文文本用空格翔试;中文轻要、中英混合文本用正則

/**
     * Draws the text on the picture.
     * @param string $text Text to draw. May contain newline characters.
     */
    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()方法的時候伦腐,遇到中文文本,我們第二個參數(shù)傳true就可以了失都。

//4柏蘑,使用gd-text包來添加一段中文文本:
    $text2 = '你好,世界粹庞,學(xué)無止境咳焚。你好,世界庞溜,學(xué)無止境革半。你好碑定,世界,學(xué)無止境又官。你好延刘,世界,學(xué)無止境六敬。你好碘赖,世界,學(xué)無止境外构。';
    $box->setBox(52, 550, 370, 200);
    $box->setTextAlign('left', 'top');
    $box->draw($text2,true);
image.png

至此普泡,使用GD庫為圖片添加文字且自動換行的分享到此結(jié)束,希望對你有所幫助审编。
下一次分享使用GD庫動態(tài)生成分銷海報

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撼班,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子垒酬,更是在濱河造成了極大的恐慌砰嘁,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伤溉,死亡現(xiàn)場離奇詭異般码,居然都是意外死亡,警方通過查閱死者的電腦和手機乱顾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門板祝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人走净,你說我怎么就攤上這事券时。” “怎么了伏伯?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵橘洞,是天一觀的道長。 經(jīng)常有香客問我说搅,道長炸枣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任弄唧,我火速辦了婚禮适肠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘候引。我一直安慰自己侯养,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布澄干。 她就那樣靜靜地躺著逛揩,像睡著了一般柠傍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辩稽,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天惧笛,我揣著相機與錄音,去河邊找鬼逞泄。 笑死徐紧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炭懊。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼拂檩,長吁一口氣:“原來是場噩夢啊……” “哼侮腹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起稻励,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤父阻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后望抽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體加矛,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年煤篙,在試婚紗的時候發(fā)現(xiàn)自己被綠了斟览。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡辑奈,死狀恐怖苛茂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸠窗,我是刑警寧澤妓羊,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站稍计,受9級特大地震影響躁绸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜臣嚣,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一净刮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茧球,春花似錦庭瑰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽督暂。三九已至,卻和暖如春穷吮,著一層夾襖步出監(jiān)牢的瞬間逻翁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工捡鱼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留八回,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓驾诈,卻偏偏與公主長得像缠诅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子乍迄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容