利用PHP實現文字繪製到新的圖片上的功能
思想和行動 總有一個不能落後於人
雖然寫出來了js實現文字和圖片載入到一起生成一個新的圖片的功能,但是我沒有用js實現一個把生成的圖片下載到本地的過程,請賭神看了看,賭神說他是用的php寫的,我想既然他用php寫了,我用js就不太方便獲得指導啊,於是乎就順便看了一下如何用php實現該功能。
百度了一下發現有現成的程式碼,所以為了方便我也就不浪費時間了,直接copy了人家的程式碼。
function generateImg($source, $text1, $text2, $text3, $font = './msyhbd.ttf') { $date = '' . date ( 'Ymd' ) . '/'; $img = $date . md5 ( $source . $text1 . $text2 . $text3 ) . '.jpg'; if (file_exists ( './' . $img )) { return $img; } $main = imagecreatefromjpeg ( $source ); $width = imagesx ( $main ); $height = imagesy ( $main ); $target = imagecreatetruecolor ( $width, $height ); $white = imagecolorallocate ( $target, 255, 255, 255 ); imagefill ( $target, 0, 0, $white ); imagecopyresampled ( $target, $main, 0, 0, 0, 0, $width, $height, $width, $height ); $fontSize = 18;//磅值字型 $fontColor = imagecolorallocate ( $target, 255, 0, 0 );//字的RGB顏色 $fontBox = imagettfbbox($fontSize, 0, $font, $text1);//文字水平居中實質 imagettftext ( $target, $fontSize, 0, ceil(($width - $fontBox[2]) / 2), 190, $fontColor, $font, $text1 ); $fontBox = imagettfbbox($fontSize, 0, $font, $text2); imagettftext ( $target, $fontSize, 0, ceil(($width - $fontBox[2]) / 2), 370, $fontColor, $font, $text2 ); $fontBox = imagettfbbox($fontSize, 0, $font, $text3); imagettftext ( $target, $fontSize, 0, ceil(($width - $fontBox[2]) / 2), 560, $fontColor, $font, $text3 ); //imageantialias($target, true);//抗鋸齒,有些PHP版本有問題,謹慎使用 imagefilledpolygon ( $target, array (10 + 0, 0 + 142, 0, 12 + 142, 20 + 0, 12 + 142), 3, $fontColor );//畫三角形 imageline($target, 100, 200, 20, 142, $fontColor);//畫線 imagefilledrectangle ( $target, 50, 100, 250, 150, $fontColor );//畫矩形 //bof of 合成圖片 $child1 = imagecreatefromjpeg ( 'http://gtms01.alicdn.com/tps/i1/T1N0pxFEhaXXXxK1nM-357-88.jpg' ); imagecopymerge ( $target, $child1, 0, 400, 0, 0, imagesx ( $child1 ), imagesy ( $child1 ), 100 ); //eof of 合成圖片 @mkdir ( './' . $date ); imagejpeg ( $target, './' . $img, 95 ); imagedestroy ( $main ); imagedestroy ( $target ); imagedestroy ( $child1 ); return $img; } //http://my.oschina.net/cart/ generateImg ( 'http://1.popular.sinaapp.com/munv/pic.jpg', 'my.oschina.net/cart', 'PHP文字水平居中', '3個字' ); exit ();
簡單的介紹一下這個程式碼;
$main = imagecreatefromjpeg ( $source );//imagecreatefromjpeg() 返回一影象識別符號,代表了從給定的檔名取得的影象。所以就是從source取得影象
$width = imagesx ( $main );
$height = imagesy ( $main ); //這是可以獲得取得影象的高和寬 其實 也可以自己設定一個值 這取決於你想要的最終的影象的寬高
$target = imagecreatetruecolor($width,$height); imagecreatetruecolor 新建了一個黑色的影象 可以設定寬和高
$white = imagecolorallocate($target,255,255,255);
imagefill($target,0,0,$white);這是給target這個影象背景色調為白色。
imagecopyresample($target,$main,0,0,0,0,$width,$height,$width,$heigh);//重新取樣拷貝部分影象並調整大小
$fontSize = 18; //這個fontSize是到時候用imagettfobbox的時候會用到的。已經判斷居中的時候會用到
$fontColor = imagecolorallocate($target,255,0,0);
$fontBox = imagettfbbox($fontSize,0,$font,$text1);
imagettftext($target ,$fontSize,0,ceil(($width - $fontBox[2])/2),190,$fontColor,$text1);
重點分析一下下面幾個函式imagettfbox 和imagettftext
關於imagettfbox
imagettfbox ——取得使用TrueType字型的文字範圍 簡單查了一下 TrueType字型是非常常見的字型格式,一般用的ttf和ttc就屬於TrueType字型的範疇。
imagettfbbox($size,$angle,$fontfile,$text)第一個傳入的值是size 特質畫素角度的大小,第二個傳入的值角度,順時針計算,0的時候為三點鐘中方向,第三個傳入的值是字型的檔名,可以是URL,第四個text是要傳入的字串。
imagegettfbox()返回一個含有8個單元的陣列表示了文字外框的四個角: 這些點是相對於文字 而和角度無關,因此左上角指的是以水平方向看文字時其左上角。
0 左下角X位置
1 左下角Y位置
2 右下角X位置
3 右下角Y位置
4 右上角X位置
5 右上角Y位置
6 左上角X位置
7 左上角Y位置
——————————————————————————————————————————————————————————————————————————————
測試部分待新增。。。。。。。目前他說這個
——————————————————————————————————————————————————————————————————————————————
關於imagegettftext的使用方法,這是一個向圖片中寫入文字的方法,
一共有八個引數,缺一不可,
imagettftext($image,$size,$angle,$x,$y,$color,$fontfile,$text);
1)$image 這個是畫布資源 也就是即將要填充文字的圖片
2)$size 字型大小,其長度依賴與GD庫的版本,對於GD1來說是畫素,對於GD2來說是磅值,現在一般都是GD2了,所以運用的就是磅值。
磅值是一個長度單位,把一英寸分成72份,每一份就是1磅。磅值是一個絕對的物理單位。而畫素沒有固定大小,而是與解析度有關。高解析度的顯示器畫素就很小。
3) $angle 是旋轉角度 角度的單位是度,而不是弧度,旋轉的中心點就是引數$x,$y。
4)
5) $x ,$y被繪製字串的第一個字元的基線點,單位是畫素。這裡涉及到字型設計的基本知識--基線,這個點絕對不是左上角,而具體是什麼取決於所使用的字型是如何設計的。對於宋體、楷體、黑體等常見的字型中的漢子,這個點大概位於字型的左下部分;而對於英文字母和標點符號,則各部相同。如下圖:
6)$color 字型的顏色
7)$fontfile 字型檔案 也就是包含TrueType字型的檔案,如楷體simkai.ttf。這種檔案格式是有標準規範的,而且與平臺無關。所以可以直接把Window系統的字型檔案拷貝到Linux下面使用。
8)$text 要渲染的字串,需要注意必需是UTF-8編碼的字串。說道字串不得不提到PHP的string資料型別。雖然名為string,其實PHP語言本身並不認識各種字元編碼,他只是簡單的把string看做是動態增長的”位元組“陣列,例如strlen()就是返回的位元組數。而我們知道除了ASCLL編碼的字元和位元組是相同的外,幾乎沒有其他字元編碼中的字元對應一個位元組,例如一個漢子的UTF-8編碼佔用3個位元組。至於怎麼解釋其中字元編碼,需要專門的庫函式如iconv_srtlen()。如果字串使用的字面量,那麼其所在的PHP原始檔就必須編碼為UTF-8儲存。
關於該函式的幾個小技巧
1)字處理軟體的複雜之處
儘管這個函式可以顯示字串,但是針對與字處理軟體(如word)來說,並不能使用。因為一旦設計到對其的問題,此函式即不能使用了。因為他不能處理字間距,當然也無法實現分散對齊的功能,再加上每一行的”避首尾“(如,不能位於行首)要求,做好字處理並不簡單。
變通的方式是,首先通過複雜的公式計算出各個字元的準確位置,然後針對每一個字元呼叫此函式。
2)如何顯示加粗字型
對於本身幾勸粗體的字型檔案來說,這不存在任何問題,只要使用粗體檔案就可以了。問題是很多字型檔案沒有針對粗體單獨設計。GD庫中也沒一個能夠加粗顯示的函式。其解決方法說出來有點可笑,就是針對每個字元繪製兩次。第二次繪製的是的$x比第一次$x多一個畫素即可。
——————————————————————————————————————————————————————————————————————————————
imagejpeg($target,'./'.$img,95);
imagejpeg()從image影象以filename為檔名建立一個JPEG影象。可以依靠這個函式把上面生成的新影象儲存起來。
引數 image 返回的資源影象 filename 檔案儲存路徑,如果未設定,或者為NULL,將會直接輸出原始影象流。如果人呂這個引數而提供quality引數,使用null。
quality
quality為可選項,範圍從0(最差質量,檔案更小)到100(最佳質量,檔案最大)。預設為IJG預設的質量大約為75.
補充一下 關於圖片合成圖片的問題
//bof of 合成圖片
$child1 = imagecreatefromjpeg ( 'http://gtms01.alicdn.com/tps/i1/T1N0pxFEhaXXXxK1nM-357-88.jpg' );
imagecopymerge ( $target, $child1, 0, 400, 0, 0, imagesx ( $child1 ), imagesy ( $child1 ), 100 );
//eof of 合成圖片
在合成圖片之前首先你得引用到”GD庫可以操作的標誌“,也就是你要能夠讀取圖片的所有資訊,這時候通過imagecreatefromjpeg就可以有給定的檔名或者url建立一個新的影象,值得注意的是後面的fromjpeg,也就是說不同的操作圖片格式,可能還要使用不同的程式碼。
簡單搜尋了一下,的確發現了不同格式下操作辦法。所以說這裡設計到一些問題,比如我要批量操作一批圖片,給他們加上水印,而這些圖片存在多種格式,那麼怎麼來處理,是通過判斷圖片格式,來選擇操作方法,還是通過將一批圖片都轉換成某一種格式?或者有一種其他方法,可以實現無論格式都可以返回的辦法。
imagecopymerge這個函式,可以實現將圖片和圖片重疊組合的辦法。拷貝並並影象的一部分
imagecopymerge($dst_im,$src_im,$dst_x,$dst_y,$src_x,$src_y,$src_w,$src_h,$pct);
將src_im影象中的座標從src_x,src_y開始,寬度為src_w,高度為src_h的一部分拷貝到dst_im影象中座標為dst_x和dst_y的位置上,兩影象將根據pct來決定合併程度,其值範圍從0到100。當pct=0時,實際上什麼也沒做,當為100時對於調色盤影象本函式和imagecopy()完全一樣,它對真彩圖像實現了alpha透明。
簡單的來說就是將SRC_im影象載入到了DST影象中了,然後在pct設定透明度,100的時候就是不透明,完全覆蓋。0的時候就是全透明,
所以PHP中通過上面這段程式碼可以實現一個在圖片中增加文字
步驟1、讀取圖片 可以使用imagecreatefrom
步驟2、設定文字,設定字型,大小,顏色(顏色要通過imagecolorallocate來設定),同時位置效果可能要使用到imagegettfbox這個方法來獲得字串的畫素值,將文字填充用到imagettftext函式。
步驟3、新增圖片首先要讀取圖片,然後使用imagecopymerge函式。
步驟四 將合成後的圖片輸出要用到imagejpeg來輸出圖片
步驟五:最後合成圖片後要將與image關聯的記憶體消除。