8.3.6.1 圖像處理函數概述
PHP提供了一系列函數來實現在網站編程中對(duì)圖像進(jìn)行編輯。雖然使用這(zhè)些函數能(néng)夠實現的功能(néng)十分有限,無法和功能(néng)強大的專業圖形圖像軟件相比,但是在很多需要動态生成(chéng)圖像、自動批量處理圖像等方面(miàn),能(néng)給PHP網站開(kāi)發(fā)者帶來巨大幫助。其中最爲典型的應用有随機圖形驗證碼、圖片水印、數據統計中餅狀圖、柱狀圖的生成(chéng)等。表8-7中給列出了PHP常用的圖像處理函數。
表8-7 PHP常用圖像處理函數
PHP 5提供的圖像處理函數總數超過(guò)了100個,表8-7中僅列出了部分常用函數。
PHP的圖像處理函數都(dōu)封裝在一個函數庫中,這(zhè)就是GD庫。要使用GD庫中的函數來進(jìn)行圖像處理,必須保證安裝了GD庫。在PHP官方的标準發(fā)行版本中,都(dōu)包含了這(zhè)個庫。如本書介紹的PHP 5版本,這(zhè)個GD庫存放在PHP安裝目錄下的ext子目錄下,名爲php_gd2.dll。讀者如果擔心自己的PHP版本是否包含這(zhè)個函數庫,可以打開(kāi)PHP安裝目錄查找一下。
并不是php_gd2.dll庫文件存在,就可以使用這(zhè)些函數了。在默認的php.ini設置中,這(zhè)個庫并不自動載入。所以,需要首先打開(kāi)這(zhè)個庫的自動載入功能(néng),這(zhè)樣這(zhè)個庫中的函數就像PHP标準函數一樣可以直接在程序中使用了。打開(kāi)的方法很簡單,用記事(shì)本打開(kāi)php.ini配置文件,利用查找功能(néng)找到“;extension=php_gd2.dll”這(zhè)一行,將(jiāng)最前面(miàn)的分号去掉,然後(hòu)保存,重新啓動IIS(Apache),這(zhè)時候GD庫已經(jīng)被自動加載了。如圖8-20所示。
圖8-20 開(kāi)啓GD圖像函數庫
若要确定此函數庫是否已經(jīng)被成(chéng)功加載,可以打開(kāi)第2章中講過(guò)的PHP環境信息顯示程序,也就是phpinfo()程序,查看列出的信息中是否有GD一項。該項目中詳細列出了當前PHP的GD庫信息,如圖8-21所示。
圖8-21 GD庫信息
由于本部分函數個數較多,而且具體使用方法較爲複雜,要在很有限的篇幅内進(jìn)行一個較全面(miàn)的介紹是十分困難的,這(zhè)裡(lǐ)僅給出兩(liǎng)個例子,讓讀者先體會一下PHP圖像處理函數的簡單使用。對(duì)表中列出的其他函數以及未在表中列出的函數,感興趣的讀者可以參考PHP手冊進(jìn)行深入學(xué)習。
8.3.6.2 PHP基本繪圖
通過(guò)下面(miàn)一個例子來學(xué)習有關用PHP進(jìn)行基本繪圖的方法。
1: <?php
2: //程序8-22.php:圖像處理函數使用舉例
3: header("Content-type: image/png");
4: $im = @imagecreate(200, 100) or die("無法創建圖像流");
5: @imagecolorallocate($im, 240, 150, 255);
6: $t_color1 = imagecolorallocate($im, 0, 0, 0);
7: $t_color2 = imagecolorallocate($im,100,100,100);
8: imagestring($im, 5, 8, 10, "I like PHP5!", $t_color1);
9: imagestringup($im,5,8,90,"Hello!",$t_color2);
10: imageellipse($im,65,65,55,55,$t_color1);
11: imageellipse($im,65,65,55,55,$t_color1);
12: imagefilledrectangle($im,110,95,160,30,$t_color2);
13: imagepng($im);
14: imagedestroy($im);
15: ?>
程序8-22.php創建了一幅PNG圖像,并且在圖像上面(miàn)進(jìn)行繪圖操作。程序運行結果如圖8-22所示。
圖8-22 程序8-22.php的運行結果
程序8-22.php第3行指定了圖像的類型,即png圖像,這(zhè)樣8-22.php雖然是一個PHP程序,但是其作用是動态生成(chéng)一張圖像,因此幾乎等同于一張圖像。在本程序中普通的輸出語句如echo等都(dōu)是無效的,這(zhè)一點讀者應當注意。
第4行用imagecreate()函數創建一幅新圖像,兩(liǎng)個參數爲圖像的寬度和高度,單位是像素。此函數返回此圖像的數據流,存放于$im變量中。
第5行用imagecolorallocate()函數設置了圖像的背景顔色。4個參數分别爲圖像流、R色值、G色值、B色值。3個色值合并即産生了RGB色值。這(zhè)裡(lǐ)的240,150,255運行之後(hòu)顯示淡紫色。另外(0,0,0)爲黑色,(255,255,255)爲白色,(255,0,0)爲紅色等。關于RGB顔色的有關詳細信息請讀者自行查閱有關資料。
第6~7行分别生成(chéng)了2種(zhǒng)顔色,存在的不同的變量中以備後(hòu)面(miàn)使用。第一種(zhǒng)爲黑色,第二種(zhǒng)爲淺灰色。
第8行用imagestring()函數在圖像上“寫入”了一個字符串。6個參數分别表示圖像流、所用字體、寫入點的x坐标、寫入點的y坐标、要寫入的字符串、字符串顔色。這(zhè)裡(lǐ)面(miàn)有兩(liǎng)點值得注意:第一點是函數的第二個參數取值範圍爲1~5,分别代表了不同大小和是否加粗的5種(zhǒng)字體,讀者可以試着修改此參數來觀察程序運行效果。第二點是這(zhè)裡(lǐ)的x,y坐标都(dōu)是相對(duì)于圖像的左上角,最左上角坐标爲(0,0),向(xiàng)右爲x軸,向(xiàng)下爲y軸。單位都(dōu)是像素。
第9行用imagestringup()函數向(xiàng)圖像中豎向(xiàng)寫入一個字符串。函數的參數含義與imagestring()函數相同。
第10行用imageellipse()函數在圖像中繪制了一個圓。函數第一個參數爲圖像流,最後(hòu)一個爲繪圖所用顔色,第2、3、4、5個參數分表表示圓心的x坐标、圓心的y坐标、圓的x方向(xiàng)半徑長(cháng)度、圓的y方向(xiàng)半徑長(cháng)度。在本例中,繪制了一個圓心在(65,65)這(zhè)個點,半徑爲55的正圓。如果要繪制一個橢圓,隻需要确定圓心位置,然後(hòu)分别設置x方向(xiàng)半徑和y軸方向(xiàng)半徑即可。當這(zhè)兩(liǎng)個半徑相等時是一個圓,不相等時是一個橢圓。
第11行用imagefilledrectangle()函數繪制了一個矩形,并對(duì)矩形進(jìn)行顔色填充。第一個參數爲圖像流,最後(hòu)一個參數爲填充顔色。第2、3、4、5個參數的含義分别爲矩形左上角x坐标、矩形左上角y坐标、矩形右下角x坐标、矩形右下角y坐标。也就是說隻要提供矩形的左上角和右下角坐标,即可繪制此矩形。
第12行用imagepng()函數將(jiāng)此圖像流輸出爲一張png格式的圖片。也就是在浏覽器中看到的圖片。
第13行銷毀了這(zhè)個圖像流。
在本例中除了png格式,還(hái)可以把圖像輸出爲jpg、gif等常用的格式,隻需要更改一下程序中第3行所指定的圖像類型即可。
8.3.6.3 網站圖形驗證碼制作
圖像驗證碼程序是當前Web開(kāi)發(fā)中常用的程序。本章學(xué)習了PHP的圖像處理函數,結合前面(miàn)章節學(xué)習的session函數以及表單數據提交技術,可以寫出一個完整的圖像驗證碼程序。
驗證碼在網站中的作用一般是防止惡意“灌水”,也就是惡意發(fā)布垃圾信息。如果沒(méi)有驗證碼,攻擊者可以利用輔助軟件實現自動提交、自動注冊等。由于軟件執行的效率高、速度快且可以連續工作,因此常用來被攻擊某個網站,制造大量垃圾數據,嚴重影響網站正常運行。
采用了驗證碼的方式之後(hòu),由于驗證碼每次都(dōu)不一樣,隻有驗證碼輸入正确才能(néng)提交信息,這(zhè)樣輔助軟件就無法随意向(xiàng)服務器提交信息了。因此,驗證碼的設計也有一些原則,如驗證碼的生成(chéng)是随機的,無規律可循。另外,有的輔助軟件有文字識别功能(néng),能(néng)夠從圖片中辨析出文字,因此驗證碼中的數字可以采用随機的顔色,而且七扭八歪不易辨認。總之,最理想的驗證碼應該是人的肉眼可以很容易地辨認出來,但是用軟件識别就極爲困難。
鑒于此,在設計這(zhè)個驗證碼程序時,就不是簡單的創建一幅圖片,然後(hòu)随機生成(chéng)幾個數字寫上去,而是再加入一些幹擾。用PHP提供的圖像處理函數,可以在圖像上加入一些密密麻麻的像素點,然後(hòu)随機繪制兩(liǎng)條虛線,再將(jiāng)幾個數字的位置打亂。這(zhè)樣,機器識别就變得十分困難了。
本實例用到以下3個文件。
8-23-showimg.php:生成(chéng)驗證碼,將(jiāng)驗證碼寫入圖片,并輸出圖片。
8-23-login.html:調用showimg.php,將(jiāng)用戶輸入的驗證碼提交到check.php進(jìn)行驗證。
8-23-check.php:用來驗證用戶輸入的驗證碼是否正确。
下面(miàn)就來看一下具體的代碼。
1: <?php
2: //文件8-23-shoimg.php:生成(chéng)驗證碼圖片,并輸出
3: //随機生成(chéng)一個4位數的數字驗證碼
4: $num="";
5: for($i=0;$i<4;$i ){
6: $num .= rand(0,9);
7: }
8: //4位驗證碼也可以用rand(1000,9999)直接生成(chéng)
9: //將(jiāng)生成(chéng)的驗證碼寫入Session,備驗證頁面(miàn)使用
10: session_start();
11: $_SESSION["Checknum"] = $num;
12: //創建圖片,定義顔色值
13: header("Content-type: image/PNG");
14: srand((double)microtime()*1000000);
15: $im = imagecreate(60,20);
16: $black = ImageColorAllocate($im, 0,0,0);
17: $gray = ImageColorAllocate($im, 200,200,200);
18: imagefill($im,0,0,$gray);
19: //随機繪制兩(liǎng)條虛線,起(qǐ)幹擾作用
20: $style = array($black, $black, $black, $black, $black, $gray, $gray,
$gray, $gray, $gra y);
21: imagesetstyle($im, $style);
22: $y1=rand(0,20);
23: $y2=rand(0,20);
24: $y3=rand(0,20);
25: $y4=rand(0,20);
26: imageline($im, 0, $y1, 60, $y3, IMG_COLOR_STYLED);
27: imageline($im, 0, $y2, 60, $y4, IMG_COLOR_STYLED);
28: //在畫布上随機生成(chéng)大量黑點,起(qǐ)幹擾作用;
29: for($i=0;$i<80;$i ){
30: imagesetpixel($im, rand(0,60), rand(0,20), $black);
31: }
32: //將(jiāng)四個數字随機顯示在畫布上,字符的水平間距和位置都(dōu)按一定波動範圍随機生成(chéng)
33: $strx=rand(3,8);
34: for($i=0;$i<4;$i ){
35: $strpos=rand(1,6);
36: imagestring($im,5,$strx,$strpos, substr($num,$i,1), $black);
37: $strx =rand(8,12);
38: }
39: ImagePNG($im);
40: ImageDestroy($im);
41: ?>
程序中的重要位置都(dōu)已經(jīng)做了注釋,再此不再詳細講解。本程序運行後(hòu)可以在浏覽器中生成(chéng)一張帶有驗證碼的圖片。每次刷新程序都(dōu)會生成(chéng)一個新驗證碼。
1: <!--文件8-23-login.html:圖形驗證碼程序-->
2: <HTML>
3: <HEAD>
4: <TITLE>圖形驗證碼程序</TITLE>
5: </HEAD>
6: <BODY>
7: <form action="8-23-check.php" method="post">
8: <img src="8-23-showimg.php"><br>
9: 請輸入驗證碼:<input type="text" name="passcode">
10: <input type=submit value="确定">
11: </form>
12: </BODY>
13: </HTML>
本程序是一段純HTML代碼,無需多做解釋。惟一值得注意的是,在調用這(zhè)個圖片時,采用“<img src=“8-23-showimg.php”>”的方式。因爲驗證碼圖片本身是一張圖片,所以使用<img>标簽來引用。而這(zhè)張圖片又是用PHP程序生成(chéng)的,因此直接用“src= 8-23-showimg.php”來調用。運行結果如圖8-23所示。
圖8-23 程序8-23-login.html的運行結果
1: <?php
2: //驗證用戶輸入的驗證碼是否正确
3: session_start();
4: $passcode=$_SESSION["Checknum"];
5: $usercode=$_POST["passcode"];
6: if($passcode == $usercode){
7: echo "驗證碼正确!驗證通過(guò)!";
8: }else{
9: echo "驗證碼輸入錯誤!驗證失敗!";
10: }
11: ?>
程序第3行是將(jiāng)session中存儲的正确的驗證碼讀取出來。第4行將(jiāng)用戶輸入的驗證碼接收過(guò)來。然後(hòu)進(jìn)行比較,如果相等,則說明用戶輸入的驗證碼正确,否則不正确。
8.3.6.4 圖片水印制作
不僅可以直接創建一個圖像流來繪制圖形,還(hái)可以將(jiāng)一張已有的圖片作爲圖像流讀入,然後(hòu)在此基礎上對(duì)圖像進(jìn)行處理。這(zhè)一功能(néng)常用來制作圖像水印。所謂圖像水印,就是在圖像上标上一些特殊的圖形或符号,用來作爲圖像所有者的标志或者防止圖片被盜用。下面(miàn)我們就看一個這(zhè)樣的例子。
本例使用了一張原始圖片pic.jpg,現在用PHP將(jiāng)此圖片進(jìn)行處理,在圖片表面(miàn)按一定規律加上文字标簽,産生水印效果,使之不能(néng)被直接盜用。
1: <?php
2: //文件8-24.php:爲圖片加水印
3: header("Content-type: image/jpeg");
4: $im = imagecreatefromjpeg("pic.jpg");
5: $white = imagecolorallocate($im,255,255,255);
6: $width=imagesx($im);
7: $height=imagesy($im);
8: $x=0;
9: $y=0;
10: while($x<$width && $y<$height){
11: imagestring($im,2, $x,$y,"https://www.xxx.com", $white);
12: $x =20;
13: $y =20;
14: }
15: imagejpeg($im);
16: imagedestroy($im);
17: ?>
本程序第3行設定本頁面(miàn)輸出類型爲jpeg圖像。
第4行用imagecreateformjpeg()函數打開(kāi)了一張圖片pic.jpg,并返回此圖片的數據流。
第5行定義了一個顔色(白色)。
第6~7行用imagesx()和imagesy()函數取得圖片pic.jpg的原始尺寸。
第8~9行定義了用于控制文字添加位置的兩(liǎng)個變量。
第10~14行用循環向(xiàng)圖片中添加多行文字,用$x和$y兩(liǎng)個變量控制位置和循環次數。
第15行輸出此圖片,第16行銷毀數據流。
程序運行前和運行後(hòu)的圖像分别如圖8-24和圖8-25所示。
圖8-24 原始圖片
圖8-25 程序8-24.php的運行結果
可以看到,處理的後(hòu)的圖片上加入了文字标記,這(zhè)就基本達到了處理意圖。但是同時也可以看出,處理後(hòu)的圖片由于文字的加入影響了圖像的觀賞性。因此水印如何加,加在什麼(me)位置,即能(néng)起(qǐ)到水印的作用,又不嚴重影響美觀,才是在處理中最應考慮的。
PHP的圖像處理函數就介紹這(zhè)些,希望讀者對(duì)此有一個基本的了解,爲以後(hòu)深入學(xué)習打下基礎。
php提供了豐富的圖像處理函數,主要包括如下幾種(zhǒng): ①獲取圖像信息的函數 ②創建與銷毀圖像的函數 ③載入圖像的函數 ④輸出圖像的函數 ⑤分配/取消圖像顔色的函數 ⑥拷貝圖像的函數 ⑦合并圖像的函數 ⑧繪制線段與圓弧的函數 ⑨圖像填充函數
PHP提供了一系列函數來實現在網站編程中對(duì)圖像進(jìn)行編輯,其中最爲典型的應用有随機圖形驗證碼、圖片水印、數據統計中餅狀圖、柱狀圖的生成(chéng)等。
php提供了豐富的圖像處理函數