一起學習PHP中GD庫的使用(三)

上篇文章我們已經學習了一個 GD 庫的應用,那就是非常常用的制作驗證碼的功能。不過在現(xiàn)實的業(yè)務開發(fā)中,這種簡單的驗證碼已經使用得不多了,大家會制作出更加復雜的驗證碼來使用。畢竟現(xiàn)在的各種外掛軟件已經能夠輕松地破解這種簡單的圖片驗證碼了。當然,我們也可以簡單地對他進行變形,比如使用中文然后按順序點擊之類的,這些都比較簡單地就能實現(xiàn)。更復雜的驗證碼則推薦使用一些開源的庫或者api來實現(xiàn)。

今天,我們將繼續(xù)學習 GD 庫的一些常用的應用。依然是通過一些小例子來進行學習,同樣也是我們在日常開發(fā)中非常常用的一些功能。

生成縮略圖

在日常的開發(fā)過程中,不管是客戶還是我們自己在后臺上傳的圖片,大小可能都不一定是我們需要的尺寸,這個時候縮略圖的功能就比較重要了。一般我們會在保留原圖的基礎上生成對應原圖的一張縮略圖用于前臺統(tǒng)一尺寸頁面的展示。

$w = imagesx($im);
$h = imagesy($im);

$imNew = imagecreatetruecolor($w / 2, $h / 2);

imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);

header("Content-type: image/jpg");
imagejpeg($imNew);
imagedestroy($imNew);

上述代碼中,我們生成的縮略圖是原圖的一半大小,使用的就是 imagecopyresized() 這個函數,它的參數依次是新圖畫布、原圖、新圖的x和y坐標起始點、原圖的x和y坐標起始點、新圖的大小、原圖的大小。參數比較多,但也比較好理解,就是將原圖縮小到指定的大小并放到新的畫布上就可以了。

https://upload-images.jianshu.io/upload_images/10153099-54ca3a5303453d02.png

imagesx() 和 imagesy() 函數不要從字面理解為什么 x 、 y 坐標點之類的,它們其實是獲得圖像句柄文件的寬和高。如果我們輸出的是 jpg 格式的圖片,還可以指定它的壓縮比率。

$w = imagesx($im);
$h = imagesy($im);

$imNew = imagecreatetruecolor($w / 2, $h / 2);

imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);

header("Content-type: image/jpg");
imagejpeg($imNew, null, 10);
imagedestroy($imNew);

也就是 imagejpeg() 函數的最后一個參數,就和 PS 導出圖片時的壓縮比率一樣,如果數字越小,壓縮比越高,數字越大,壓縮比越低,圖片質量也就越好。默認值為 75 ,可以設置從 0 到 100 的壓縮比。第二個參數依然是保存圖片的路徑,我們這里測試的代碼還是直接從瀏覽器輸出的,所以我們這里是給的一個 null 。

https://upload-images.jianshu.io/upload_images/10153099-c61e7221383733cb.png

從圖片的畫質來看,確實比上一張直接縮小的圖片模糊了許多。當然,圖片的大小也小了很多。對于網站的優(yōu)化來說,jpg 圖片的壓縮比例一般都會在默認值的 75 左右。如果太小就會出現(xiàn)這種過于模糊的情況從而影響用戶的體驗。具體業(yè)務具體分析,需要多大的圖片大小還是要根據我們實際的情況來定。

生成指定大小的等比例縮略圖

還有一種業(yè)務情況是,我們前臺的圖片展示大小都是一樣的,比如商品圖片在列表中的顯示。這時,很多圖片直接壓縮可能就會丟失比例,比如我們上傳了一張 16:9 的大寬圖,而前臺列表頁的圖片位置是 4:3 的圖,這里我們就要等比例按照最大寬度或者最大高度進行縮小,同時多出來的部分留白邊或者透明邊,這時,只要計算一下圖片的比例情況就可以了。

$w = imagesx($im);
$h = imagesy($im);

$imNew = imagecreatetruecolor(202, 152);
imagefill($imNew, 0, 0, imagecolorallocate($imNew, 255, 255, 255));
imagerectangle($imNew, 0, 0, 201, 151, imagecolorallocate($imNew, 0, 0, 0));

$sW = 0;
$sH = 0;
if ($w / $h > 200 / 150) {
    $q = 200 / $w;
    $sH = $h * $q;
    $sW = $w * $q;
    $sX = 0;
    $sY = (150 - $sH) / 2;
} else {
    $q = 150 / $h;
    $sH = $h * $q;
    $sW = $w * $q;
    $sX = (200 - $sW) / 2;
    $sY = 0;
}

imagecopyresized($imNew, $im, $sX + 2, $sY + 1, 0, 0, $sW, $sH, $w, $h);

header("Content-type: image/jpg");
imagejpeg($imNew);
imagedestroy($imNew);

在測試代碼中,我們規(guī)定的大小是 200*150 的圖片大小,也就是 4:3 的圖片規(guī)格。而需要操作的圖片則是 300*244 的一張不太規(guī)范的圖片。這時,我們通過計算 寬/高 的比例,來確定是以寬為基準進行縮小還是以高為基準進行縮小。如果原圖的寬高比大于我們規(guī)定的圖片寬高比,則認為是以寬度為基準進行縮小。反之,就是以高度進行縮小。同樣地,具體的寬高結果的算法都都是基于對應的比率進行等比例縮小的。同時,我們還要計算圖片的位置,要放在居中的位置。最后,再將縮小的大小放入到指定大小的畫布中。

https://upload-images.jianshu.io/upload_images/10153099-5ac882e09ccd069d.png

我們這段測試代碼中的畫布多了兩個像素,是為了畫那個黑色的邊框,目的也是為了演示能夠看清楚。

可以看到,我們等比例縮放之后是以原圖的高為基準進行縮放的,所以圖片的兩邊會出現(xiàn)白邊。如果是以寬為基準的,那么圖片上下會出現(xiàn)白邊。當然,如果原圖的比例和我們需要的比例是一樣的,就會完整地撐滿整個畫布。大家可以自己用其它大小的圖片測試一下。

圖片加水印

除了縮略圖之外,加水印的功能也是很多業(yè)務開發(fā)中必備的功能。直接的文字水印其實就不用多說了,上篇文章中的 imagettftext() 就可以直接加了,只需要給它用 imagecolorallocatealpha() 函數指定一個帶透明的顏色就可以了。今天我們主要來講的是圖片水印的添加。

$imNew = imagecreatetruecolor(150, 30);

imagecolortransparent($imNew, imagecolorallocatealpha($imNew, 255, 255, 255, 128));
imagesavealpha($imNew, true);

$font = '../font/msyh.ttf';
imagettftext($imNew, 16, 0, 11, 21, imagecolorallocate($imNew, 255, 255, 255), $font, '硬核項目經理');

if (imagesx($im) > 150 + 10 && imagesy($im) > 60 + 10) {
    imagecopy($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 30 - 10, 0, 0, 150, 30);

    imagecopymerge($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 60 - 10, 0, 0, 150, 30, 50);
}

header("Content-type: image/jpg");
imagejpeg($im);
imagedestroy($im);

首先,我們通過 imagecolortransparent() 和 imagesavealpha() 指定一個透明畫布。然后通過 imagettftext() 生成一張文字圖片。注意,這里是圖片哦,不是直接添加的文字。

接著,使用 imagecopy() 或 imagecopymerge() 來將水印圖片拷貝到原始圖片上。這兩個函數的區(qū)別就是 imagecopymerge() 在圖片合并的時候多了一個參數可以指定通道的透明度,也就是說,如果是一張不帶透明度的圖片可以直接使用這個函數來讓圖片增加透明的效果。

在添加水印之前的判斷是用于判斷圖片大小是否適合添加水印,如果圖片比水印文件還小的話,那么就不要添加水印了,或者再將水印也縮小后再進行添加。

https://upload-images.jianshu.io/upload_images/10153099-cbceccaf68071cbc.png

這樣,簡單地水印添加就完成了。網上其實能找到很多前輩已經封裝好的添加水印的類,或者 Composer 中也有很多現(xiàn)成的庫,這里只是手寫一個簡單的效果供大家學習復習。

總結

關于圖片 GD 庫的功能函數還有很多,但說實話,筆者現(xiàn)在都已經用得不多了。為什么呢?在實際的業(yè)務開發(fā)中,大家其實都已經習慣使用 oss 、七牛、upyun 之類的云存儲了。不管是圖片縮放、添加水印,甚至是簡單地進行一些 PS 編輯,都非常方便。而且最主要的是不需要再占用我們的服務器存儲資源以及帶寬資源,何樂而不為呢。像我現(xiàn)在的工作中,程序代碼服務器基本上只需要原始的 20G 左右大小就可以了,只是運行代碼,不存儲上傳的文件、圖片以及靜態(tài)資源。

測試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202012/source/3.一起學習PHP中GD庫的使用(三).php

參考文檔:

https://www.php.net/manual/zh/book.image.php

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容