程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP之圖形處理

PHP之圖形處理

編輯:關於PHP編程

圖形處理

 

PHP 的圖形處理,主要功能集中在 PHP 的圖形處理函數。

 

需要先掌握一些要點。什麼叫圖片,怎麼顯示圖片。

 

所謂的圖片,其實也是一種文件,只是內容不是我們肉眼直接可見的。如果我們用記事本打開一張圖片,只會看到一片亂碼。其實這些亂碼,只是相對我來說是亂碼。對於可以讀寫它的程序來說,一點都不亂。如果我們知道一種圖片的格式,我們就可以自己生成一張圖片。就像我們最早的時候,制作的記事本留言本一樣。

 

把一些特殊格式的數據,保存到一個文件,就可以生成一張圖片。反之,我們如果用 PHP 直接輸出這些內容,浏覽器也會認為這是一張圖片。

 

我們先來證實一下這一點,同學們先准備好一張圖片。建議小一點的, JPG 格式就可以了。然後我們使用 PHP 讀取這張圖片,就像普通文件一樣讀取。

 

<?PHP

 

$file = "1.jpg";

 

$fp = fopen($file, "rb");

$data = fread( $fp, filesize($file));

fclose($fp);

 

echo $data;

?>

 

相信對於同學們來說,這個代碼沒有什麼問題吧。

 

打開文件,讀取內容(所有字節),關閉文件,輸出內容。

 

有沒有同學試一下,這個代碼運行後會輸出什麼,截個圖上來看一下。

 

 

也許有同學會奇怪吧,怎麼是亂碼。

因為浏覽器默認,認為我們的 PHP 輸出是文本。即使是亂碼,我們需要告訴浏覽器,這是一張圖片。這個需要用 header 函數,發送頭信息,告訴浏覽器,當前輸出的內容,是格片格式。

Header("Content-type: image/jpeg");

這是 JPG 格式圖片使用的頭信息,內容類型:圖片/jpeg,需要加在 echo 之前。

 

<?PHP

 

$file = "1.jpg";

 

$fp = fopen($file, "rb");

$data = fread( $fp, filesize($file));

fclose($fp);

 

Header("Content-type: image/jpeg");

echo $data;

?>

同學們再試一下。

 

這個代碼證明了一點:即使輸出的是亂碼,只要浏覽器知道它是什麼內容;它就能正確顯示。

相對的,如果我們把讀出來的內容,保存到另一個文件,就可以復制這張圖片。

在這裡,可能會有一些同學會有一些誤解。認為,這裡還是一個網頁。各位同學可以試一下,在打開的網頁空白處,點一下鼠標右鍵,查看源文件,會發現,沒有這個選項。即使有,也是灰的。這是因為,這個不是一個頁面,浏覽器已經認為,我們這個 PHP 程序,是一張圖片了。

平時我們使用 PHP 進行任何形式的輸出時,浏覽器認為這是一個 HTML 網頁,才能看到源代碼。

 

如果我們輸出的是圖片內容,要能正確顯示,就必須告訴浏覽器,本次輸出,別把我當成網頁,而是當成圖片。也就是說,我們的 php 程序,是一張圖片。如果要想在別的網頁使用這張圖片,需要像平時一樣 <img 標記來調用這張圖片。

<img src="img.php" />

把這個 PHP 程序,當成一張圖片來對待,而不能直接在這個程序寫上。

<img src="<?PHP 我們剛才的代碼 ?>" />

這樣是不對的,這樣只會導致一個結果。

<img src="一堆亂碼" />

這是不可能顯示得出來的。

所以,使用 PHP 處理圖片的程序,一定是單項功能的 PHP 程序。除非你不輸出這張圖片,而只是把它保存起來。

 

<?PHP

$file = "1.jpg";

 

$fp = fopen($file, "rb");

$data = fread( $fp, filesize($file));

fclose($fp);

 

$fp = fopen("2.jpg", "wb");

fwrite($fp, $data);

fclose($fp);

 

?>

<img src="2.jpg" />

如果代碼是這麼寫,就是另一回事,沒有錯。把圖片保存到另一個地方,然後輸出 HTML 調用這張圖片。要直接輸出圖片的 PHP 程序,一定不可能含有別的輸出,沒有用。只能單純的輸出圖片的內容,就是那堆亂碼。

好了,讀取圖片,輸出圖片都沒有問題了。

 

文件的內容是特殊格式,我們看都看不懂,怎麼處理它呢?

PHP 提供了專門的圖形處理函數。

 

圖形處理函數庫,有一個專用的名字,叫 GD庫。

 

這個函數庫並不是 PHP 自帶的。需要在安裝 PHP 的時候,在 php.ini 裡設置加載。

庫文件名叫 php_gd2.dll。PHP 的安裝包裡就有,在 ext 目錄下。如果哪位同學的 php.ini 裡還沒加載 GD庫,請現在打開它。

 

這樣,PHP 才有圖形處理函數可用。

當前 PHP 自帶的 GD 庫版本是 2.0.28。PHP 4 帶的是 gd 2.0,PHP 3 時代是 gd 1.6。

為什麼要提這個呢?

因為 gd 2.0 的時候,因為 GIF 圖片的版權問題。PHP 做為免費開源的語言,無法向 GIF 的版權商提供版權費,所以只能暫停對 GIF 圖片的支持。PHP 5 以後,GIF 版權到期, 我們的 PHP 才重新支持 gif 圖片。

 

好了,我們打開 PHP 手冊,看一下 Image 圖像函數。

函數很多,但是,大致上可以分成四類:創建,繪畫,設置,輸出。

 

如果要創建一張圖片,可以使用 imagecreate 函數。從函數名就可以看得出來了,創建圖像。從手冊上,可以看得到語法格式。

 

返回圖像資源 imagecreate(寬度 , 高度)

 

寬度和高度以像素為單位。

 

還有另一個函數,imagecreatetruecolor 新建一個真彩色圖像,支持更多顏色。

創建類的函數,都會返回一個圖片資源,有點類似於 fopen 函數的返回。資源型的數據,內部含有一個可讀寫指針,,讓我們可以對圖片進行編輯操作。

 

我們先來試試創建一張圖片,先用 imagecreate 函數好了。

為了能看到這張圖片,我們需要輸出。但是我們的經驗告訴我們,資源型的內容不能直接輸出。

圖片形函數,給我們提供了一些函數,分別是:

 

imagejpeg 以 JPG 格式輸出

imagegif  以 GIF 格式輸出

imagepng  以 PNG 格式輸出

函數格式是一樣的。

 

imagejpeg( 圖像資源 , [保存路徑])

如果需要保存這張圖片,就在第二個參數寫上文件名就可以了。如果只是希望直接輸出,第二個參數不寫就行。

我們現在先直接輸出這張圖像。

Header("Content-type: image/JPEG");

 

$img =imagecreate(100, 100);

imagejpeg($img);

創建一張 100*100 的圖像,然後用 JPG 格式輸出它。要記得告訴浏覽器,這是圖片。

運行的結果是什麼樣的呢?有哪位同學截個圖上來看看。

 

是的,會輸出一張黑色的圖片。因為我們並沒有在上面畫任何內容,也沒告訴它應該用什麼顏色。

我們先來簡單一點的操作,先在上面塗點顏色。這個需要使用 imagecolorallocate 函數。

 

函數功能是:為一幅圖像分配顏色

函數格式是

 

imagecolorallocate(圖像資源, 紅色,綠色,藍色)

三元色,分別用 0 到 255 的數字表示。0是最暗,255是最亮。如果需要白色,三色都是 255 就可以了,黑色就是三色 0,如果只要紅色,就是 255 0 0。

header("Content-type: image/jpeg");

 

$img =imagecreate(100, 100);

imagecolorallocate($img, 255,0,0);

imagejpeg($img);

我就填上個純紅好了。同學們可以自己試試,分別給紅綠藍設置一些數值,看看結果如何。這個配色,需要一些知識了。同學們也可以直接在各種畫圖工具裡得到這個顏色。

 

右下角的 紅綠藍 值就可以直接用。很多軟件都有類似的調色板,很容易可以得到各種顏色值。

這裡有一點要注意。

imagecolorallocate 函數,只有第一次使用的時候,會給圖像填上背景色,重新使用,並不會改變背景色。

header("Content-type: image/jpeg");

 

$img =imagecreate(100, 100);

imagecolorallocate($img, 255,0,0);

imagecolorallocate($img, 0, 0, 255);

imagejpeg($img);

這個代碼,並不會輸出預期的藍色。但是,並不表示函數沒有用。函數依然有效,只是這個顏色沒有被使用而已。我們可以用這個顏色,做其他用途,比如寫字。

 

我們來試試,在圖像上面寫點字。

PHP 給我們提供的函數裡面,有兩個函數可以用於在圖像上寫字,分別是 imagestring  和 imagestringup。

imagestring  是橫向寫字

imagestringup 是縱向寫字

如果用 imagestringup 寫的話,我就們看字就得扭著脖子看了。好吧,先用 imagestring。

 

imagestring 函數原型

 

imagestring(圖像資源, 字體, 開始X坐標,開始Y坐標, 要寫的字, 顏色)

PHP 自帶的字體只有5種,需要用數字1到5表示。

我們來試一下吧。

header("Content-type: image/jpeg");

 

$img =imagecreate(100, 100);

imagecolorallocate($img, 255,0,0);

 

$color = imagecolorallocate($img, 0, 0, 255);

imagestring($img, 4, 0,0, 'abcdef', $color);

 

imagejpeg($img);

 

你大爺的,好刺眼,我換白底好一點。

有沒有哪個同學試試寫個中文?結果會讓人很失望。

 

因為 PHP 自帶的字體,弱爆了,跟本無法正常顯示中文。怎麼辦呢?

自定義字體。

image 函數,給我們提供了另一個函數,可以使用自定義字體來寫字。嚴格來說是“畫字”。需要一個帶點陣格式的字體文件,而且要支持中文的,最常見的就是 ttf 類型的字體了。如果做過平面設計的同學,對這個一定不陌生,沒做過的同學,也不要緊。我們可以在我們的系統裡面,挖幾個出來用用。系統自帶的字體文件,在 C:\windows\fonts 目錄,我們可以在裡面找一個支持中文的字體。WIN 系統自帶的字體,大多數都支持中文,我挑一個微軟雅黑。回到我們的 PHP。

要使用這個字體文件來畫字,需要用 imagettftext 函數。

 

imagettftext 函數原型

 

imagettftext (圖像資源, 字體大小, 字體方向, 開始X坐標, 開始Y坐, 字體顏色, 字體文件, 要寫的字 )

我的娘哦,好多參數。估計各位同學也是第一次用這麼多參數的函數吧。

 

//創建圖片,並設置白底

$img =imagecreate(100, 100);

imagecolorallocate($img, 255,255,255);

 

//准備一個顏色,

$color = imagecolorallocate($img, 0, 0, 255);

 

//准備一個字體文件

$font = "msyhbd.ttf";

 

//圖像資源, 字體大小, 字體方向, 開始X坐標, 開始Y坐, 字體顏色, 字體文件, 要寫的字

imagettftext($img, 14, 0, 20, 20, $color, $font, "中文支持");

 

//JPG格式輸出圖像

imagejpeg($img);

這個圖像文件,如果路徑不在當前目錄下,要告訴 PHP 在哪裡。

比如 $font = "./font/msyhbd.ttf";

或者 $font = "C:\\windows\\fonts\\msyhbd.ttf";

必須讓 PHP 找得到這個字體文件

 

imagettftext($img, 14, 180, 150, 150, $color, $font, "中文支持");

 

字體方向 180度,結果就成這樣子。另外,中文在這裡必須是 utf8 編碼。這個很容易做到,把 PHP 文件轉換成 utf8 編碼就可以了。使用 gbk 編碼的同學,可以給字體轉換一下編碼。

$text = iconv("gbk", "utf-8", "中文支持");

只要有足夠的字體,我們可以讓 PHP 輸出任意樣式

$font = "FZKANGFW.TTF";

$text = iconv("gbk", "utf-8", "中文支持");

imagettftext($img, 20, 0, 150, 150, $color, $font, $text);

 

這個效果,配合預定變量 $_SERVER 可以做到一個效果。

 

$_SERVER['REMOTE_ADDR']

 

這個服務器變量,可以得到來訪者的 IP 地址。網上的各種帶 IP 顯示的圖片,就是這麼做出來的。不就是在圖片上寫幾個字麼。

 

 

好了。然後我們來學習一下。在上面畫線條。

 

畫圖函數很多。

imagedashedline - 畫一虛線

imagedestroy - 銷毀一圖像

imageellipse - 畫一個橢圓

imagefill - 區域填充

imagefilledarc - 畫一橢圓弧且填充

imagefilledellipse - 畫一橢圓並填充

imagefilledpolygon - 畫一多邊形並填充

imagefilledrectangle - 畫一矩形並填充

畫線是 imageline,其他畫圖函數,同學們可以自行參考手冊。

看來看去,不外乎原理就是:在圖像資源上,用什麼顏色,從哪個坐標開始,畫什麼。

 

imageline函數原型

 

( 圖像資料, 開始X坐標, 開始Y坐標, 結束X坐標, 結束Y坐標, 顏色 )

 

在數學中,我們知道XY坐標可以確定平面上的一個點,兩個點可以決定一個線段。

 

//創建圖片,並設置白底

$img =imagecreate(300, 300);

imagecolorallocate($img, 200,200,200);

 

//准備一個顏色,

$color = imagecolorallocate($img, 0, 0, 255);

 

//用這個顏色畫一條線

imageline($img, 0,150,  300,150,  $color);

 

//JPG格式輸出圖像

imagejpeg($img);

我的圖像是 300*300 的大小。從0,150 就是最左邊,中間位置,到最右邊,中間位置。

 

如果要畫一張網格的話,你就慢慢算座標,然後重復畫就可以了。

 

for($i=0; $i < 6; $i++) {

    $y = $i*50;

    imageline($img, 0,$y,  300,$y,  $color);

}

豎線什麼的,就不多說了。

還有其他各種線條,形狀,各位同學可以跟據手冊的說明,自行練習。

 

 

很多時候,我們圖片是現成的。我們要做的只是縮小,裁剪大小。

圖片是現成的,我們需要把圖片加載進來,跟據圖片的不同類型,我們需要不同的函數來加載。

imagecreatefromjpeg 創建一張圖像,來自JPG文件

imagecreatefromgif  GIF

imagecreatefrompng  PNG

imagecreatefromwbmp WBMP

imagecreatefromxbm  XBM

圖片是什麼類型,就用什麼函數來載入。這些函數,都屬於創建類函數。之前,我們使用寫字,畫線,都屬於繪畫類函數。這樣區分,就不覺得函數多了。很多函數其實是重復的,只是針對於不同的類型。所有的操作,都是針對於畫布,在畫布上畫什麼。

 

其實 PHP 並不能縮小一張圖片,那只是一種思路上的技巧。用的是圖像復制函數imagecopymerge。

可以把圖像的一部份,復制到另一張圖像上面,同類的還有另一個函數imagecopyresampled。都是復制圖像的一部份,復制到另一張圖像上面。這意味著,這樣的操作,需要兩個圖像。一個是原圖,一個是新生成的圖。

 

原圖,我們可以用 imagefrom 系列函數加載進來。新圖,我們可以自己創建。然後再使用圖像復制函數,從原圖復制到新圖。

如果復制的只是其中的一個區域,那就是 裁剪功能。如果復制是整個圖像大小,新圖的大小和原圖大小不同,就是改變圖片大小,也就是縮略圖,或者放大圖。

$image = "1.jpg";

//讀取圖片大小

list($width, $height) = getimagesize($image);

 

//加載圖片

$bimg = imagecreatefromjpeg($image);

 

//新建圖片,大小是原圖的一半

$simg =imagecreatetruecolor($width * 0.5, $height * 0.5);

 

//在原圖上,把原圖的全部,縮小一半,復制過來

imagecopyresampled($simg, $bimg, 0,0, 0,0, $width*0.5, $height*0.5, $width, $height );

 

//JPG格式輸出小圖像

imagejpeg($simg);

應該有同學發現了,這裡使用的是 imagecreatetruecolor 創建新圖像。真彩圖像,而不是 imagecreate。同學們可以試一下,用 imagecreate 是什麼結果。

復制圖像,我選擇了 imagecopyresampled 函數,復制並調整大小。同類函數還有 imagecopyresized。

 

imagecopyresized

imagecopyresampled

 

這兩個函數都是復制並調整大小圖像。同學們可以自己測試它們的區別。由於參數太多,我這裡幫你們做一個注釋。

 

新圖, 原圖,

新圖起點X,新圖起點Y,

原圖起點X,原圖起點Y,

新圖寬度,新圖高度,

原圖寬度,原圖高度

 

兩個一組,一起看就行了。

 

//加載圖片

$bimg = imagecreatefromjpeg($image);

 

//新建圖片,大小是原圖的一半

$simg =imagecreatetruecolor($width * 0.5, $height * 0.5);

 

//在原圖上,把原圖的全部,縮小一半,復制過來

imagecopyresampled($simg, $bimg, 0,0, $width*0.5, $height*0.5, $width, $height, $width, $height );

這個代碼的意思是

 

$simg, $bimg,  //新圖,原圖

0,0,  //從新圖的 0*0 開始畫

$width*0.5, $height*0.5, //從原圖的中心點取樣

$width, $height, //新圖和原圖等大小。

$width, $height  //到原圖的最右下角坐標結束

由於創建的圖像只有原圖的一半,這個代碼,會使得最終圖片只顯示原圖中心點開始。右下角的內容。也就是 1/4 原圖的內容,就是所謂的裁剪。

 

這些函數的參數太多,不太容易看,計算各個采樣坐標,需要更細心。

 

水印圖的原理也是一樣的。加載兩張圖,創建兩個圖像對象。然後把水印圖,復制到原圖上。面。其實都只是一個思路的技巧而已。

 

圖形函數就講到這裡。

 

我先來總結一下這一課的要點。

1、一定要先創建圖像,加載創建或自己創建。

2、只能在圖像上面繪畫,線條,形狀

3、文字只能用 UTF8 編碼,要顯示中文需要中文字體

4、圖像本身不能直接調整,只能在復制的過程中調整。

5、如果要直接輸出圖像,這個程序不能輸出其他多余的東西

6、一個直接輸出圖像的程序,要把它看成圖片來調用。

 

圖像函數。分為幾類:

創建類:imagecreate、imagecreatefromjpeg

設置類:imagecolorallocate、getimagesize

繪制類:imagecopyresampled、imageline、imagettftext

輸出類:imagejpeg、imagepng

 

其中繪制類的函數最多,函數格式也很相似,都是:

在圖像的XX坐標,繪制XX東西

 

復制操作的函數,坐標往往有8個之多。

原圖起點坐標,原圖寬高, 這就四個了;

新圖起點坐標,新圖寬高, 這裡又四個;

再加上原圖,新圖。有十來個參數。

 

所以,一般圖像處理的過程,往往調試好一個程序之後,都不願意再回頭重新改了。封裝成自定義函數吧。

比如縮略圖函數。

 

function size_img($img, $width, $height) {

   中間你就處理吧。

}

這樣提供一個圖片,指定輸出的大小,就可以生成縮略圖了。至少用起來方便多了。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved