PHP 5.0創(chuàng)建圖形的實用方法完整篇第1/3頁
我將圖形編輯程序分為兩類:一類是繪圖程序,利用這種程序可以一個像素一個像素地繪制圖像;另外一類是制圖程序,這種程序提供了一組對象,例如線、橢圓和矩形,您可以使用這些對象來組合成一幅大圖像,例如 JPEG。繪圖程序非常適合進行像素級的控制。但是對于業(yè)務(wù)圖形來說,制圖程序是比較好的方式,因為大部分圖形都是由矩形、線和橢圓組成的。
PHP 內(nèi)置的制圖基本操作與繪圖程序非常類似。它們對于繪制圖像來說功能非常強大;但是如果您希望自己的圖像是一組對象集合時,這就不太適合了。本文將向您展示如何在 PHP 圖形庫的基礎(chǔ)上構(gòu)建一個面向?qū)ο蟮膱D形庫。您將使用 PHP V5 中提供的面向?qū)ο蟮臄U展。
具有面向?qū)ο蟮膱D形支持之后,您的圖形代碼就非常容易理解和維護了。您可能還需要從一種單一的圖形源將圖形合成為多種類型的媒介:Flash 電影、SVG 等等。
目標(biāo)
創(chuàng)建一個圖形對象庫包括 3 個主要的目標(biāo):
從基本操作切換到對象上
它不使用 imageline、imagefilledrectangle 以及其他圖形函數(shù),這個庫應(yīng)該提供一些對象,例如 Line、Rectangle 和 Oval,它們可以用來制作圖像。它應(yīng)該還可以支持構(gòu)建更大的復(fù)雜對象或?qū)ο筮M行分組的功能。
可以進行 z 值排序
制圖程序讓畫家可以在畫面表面上上下移動圖形對象。這個庫應(yīng)該可以支持將一個對象放到其他對象前后的功能:它使用了一個 z 值,用來定義對象從制圖平面開始的高度。z 值越大的對象被畫得越晚,也就出現(xiàn)在那些 z 值較小的對象之上。
提供 viewport 的轉(zhuǎn)換
通常,數(shù)據(jù)的坐標(biāo)空間與圖像的坐標(biāo)空間是不同的。PHP 中的圖形基本操作是對圖像的坐標(biāo)平面進行操作的。這個圖形庫應(yīng)該支持 viewport 的規(guī)范,這樣您就可以在一個程序員熟悉的坐標(biāo)系統(tǒng)中指定圖形了,并且可以自動進行伸縮來適應(yīng)任何圖像的大小。
由于這里有很多特性,您將一步步地編寫代碼來展示這些代碼如何不斷增加功能。
基礎(chǔ)知識
讓我們首先來看一個圖形環(huán)境對象和一個名為 GraphicsObject 的接口,它是使用一個 Line 類實現(xiàn)的,功能就是用來畫線。UML 如圖 1 所示。
圖 1. 圖形環(huán)境和圖形對象接口

GraphicsEnvironment 類中保存了圖形對象和一組顏色,還包括寬度和高度。saveAsPng 方法負責(zé)將當(dāng)前的圖像輸出到指定的文件中。
GraphicsObject 是任何圖形對象都必須使用的接口。要開始使用這個接口,您所需要做的就是使用 render 方法來畫這個對象。它是由一個 Line 類實現(xiàn)的,它利用 4 個坐標(biāo):開始和結(jié)束的 x 值,開始和結(jié)束的 y 值。它還有一個顏色。當(dāng)調(diào)用 render 時,這個對象從 sx,sy 到 ex,ey 畫一條由名字指定的顏色的線。
這個庫的代碼如清單 1 所示。
清單 1. 基本的圖形庫
<?php
class GraphicsEnvironment
{
public $width;
public $height;
public $gdo;
public $colors = array();
public function __construct( $width, $height )
{
$this->width = $width;
$this->height = $height;
$this->gdo = imagecreatetruecolor( $width, $height );
$this->addColor( "white", 255, 255, 255 );
imagefilledrectangle( $this->gdo, 0, 0,
$width, $height,
$this->getColor( "white" ) );
}
public function width() { return $this->width; }
public function height() { return $this->height; }
public function addColor( $name, $r, $g, $b )
{
$this->colors[ $name ] = imagecolorallocate(
$this->gdo,
$r, $g, $b );
}
public function getGraphicObject()
{
return $this->gdo;
}
public function getColor( $name )
{
return $this->colors[ $name ];
}
public function saveAsPng( $filename )
{
imagepng( $this->gdo, $filename );
}
}
abstract class GraphicsObject
{
abstract public function render( $ge );
}
class Line extends GraphicsObject
{
private $color;
private $sx;
private $sy;
private $ex;
private $ey;
public function __construct( $color, $sx, $sy, $ex, $ey )
{
$this->color = $color;
$this->sx = $sx;
$this->sy = $sy;
$this->ex = $ex;
$this->ey = $ey;
}
public function render( $ge )
{
imageline( $ge->getGraphicObject(),
$this->sx, $this->sy,
$this->ex, $this->ey,
$ge->getColor( $this->color ) );
}
}
?>
|
測試代碼如清單 2 所示:
清單 2. 基本圖形庫的測試代碼
<?php
require_once( "glib.php" );
$ge = new GraphicsEnvironment( 400, 400 );
$ge->addColor( "black", 0, 0, 0 );
$ge->addColor( "red", 255, 0, 0 );
$ge->addColor( "green", 0, 255, 0 );
$ge->addColor( "blue", 0, 0, 255 );
$gobjs = array();
$gobjs []= new Line( "black", 10, 5, 100, 200 );
$gobjs []= new Line( "blue", 200, 150, 390, 380 );
$gobjs []= new Line( "red", 60, 40, 10, 300 );
$gobjs []= new Line( "green", 5, 390, 390, 10 );
foreach( $gobjs as $gobj ) { $gobj->render( $ge ); }
$ge->saveAsPng( "test.png" );
?>
|
這個測試程序創(chuàng)建了一個圖形環(huán)境。然后創(chuàng)建幾條線,它們指向不同的方向,具有不同的顏色。然后,render 方法可以將它們畫到圖形平面上。最后,這段代碼將這個圖像保存為 test.png。
在本文中,都是使用下面的命令行解釋程序來運行這段代碼,如下所示:
% php test.php % |
圖 2 顯示了所生成的 test.png 文件在 Firefox 中的樣子。
圖2. 簡單的圖形對象測試
這當(dāng)然不如蒙娜麗莎漂亮,但是可以滿足目前的工作需要。
[NextPage]
添加維數(shù)
我們的第一個需求 —— 提供圖形對象的能力 —— 已經(jīng)滿足了,現(xiàn)在應(yīng)該開始滿足第二個需求了:可以使用一個 z 值將一個對象放到其他對象的上面或下面。
我們可以將每個 z 值當(dāng)作是原始圖像的一個面。所畫的元素是按照 z 值從最小到最大的順序來畫的。例如,讓我們畫兩個圖形元素:一個紅色的圓和一個黑色的方框。圓的 z 值是 100,而黑方框的 z 值是 200。這樣會將圓放到方框之后,如圖 3 所示:
圖3. 不同 z 值的面
我們只需要修改一下 z 值就可以將這個紅圓放到黑方框之上。要實現(xiàn)這種功能,我們需要讓每個 GraphicsObject 都具有一個 z() 方法,它返回一個數(shù)字,就是 z 值。由于您需要創(chuàng)建不同的圖形對象(Line、Oval 和 Rectangle),您還需要創(chuàng)建一個基本的類 BoxObject,其他 3 個類都使用它來維護起點和終點的坐標(biāo)、z 值和這個對象的顏色(請參看圖 4)。
圖 4. 給系統(tǒng)添加另外一維:z 值
這個圖形庫的新代碼如清單 3 所示:
清單 3. 可以處理 z 信息的圖形庫
<?php
class GraphicsEnvironment
{
public $width;
public $height;
public $gdo;
public $colors = array();
public function __construct( $width, $height )
{
$this->width = $width;
$this->height = $height;
$this->gdo = imagecreatetruecolor( $width, $height );
$this->addColor( "white", 255, 255, 255 );
imagefilledrectangle( $this->gdo, 0, 0,
$width, $height,
$this->getColor( "white" ) );
}
public function width() { return $this->width; }
public function height() { return $this->height; }
public function addColor( $name, $r, $g, $b )
{
$this->colors[ $name ] = imagecolorallocate(
$this->gdo,
$r, $g, $b );
}
public function getGraphicObject()
{
return $this->gdo;
}
public function getColor( $name )
{
return $this->colors[ $name ];
}
public function saveAsPng( $filename )
{
imagepng( $this->gdo, $filename );
}
}
abstract class GraphicsObject
{
abstract public function render( $ge );
abstract public function z();
}
abstract class BoxObject extends GraphicsObject
{
protected $color;
protected $sx;
protected $sy;
protected $ex;
protected $ey;
protected $z;
public function __construct( $z, $color, $sx, $sy, $ex, $ey )
{
$this->z = $z;
$this->color = $color;
$this->sx = $sx;
$this->sy = $sy;
$this->ex = $ex;
$this->ey = $ey;
}
public function z() { return $this->z; }
}
class Line extends BoxObject
{
public function render( $ge )
{
imageline( $ge->getGraphicObject(),
$this->sx, $this->sy,
$this->ex, $this->ey,
$ge->getColor( $this->color ) );
}
}
class Rectangle extends BoxObject
{
public function render( $ge )
{
imagefilledrectangle( $ge->getGraphicObject(),
$this->sx, $this->sy,
$this->ex, $this->ey,
$ge->getColor( $this->color ) );
}
}
class Oval extends BoxObject
{
public function render( $ge )
{
$w = $this->ex - $this->sx;
$h = $this->ey - $this->sy;
imagefilledellipse( $ge->getGraphicObject(),
$this->sx + ( $w / 2 ),
$this->sy + ( $h / 2 ),
$w, $h,
$ge->getColor( $this->color ) );
}
}
?>
|
測試代碼也需要進行更新,如清單 4 所示。
清單 4. 更新后的測試代碼
<?php
require_once( "glib.php" );
function zsort( $a, $b )
{
if ( $a->z() < $b->z() ) return -1;
if ( $a->z() > $b->z() ) return 1;
return 0;
}
$ge = new GraphicsEnvironment( 400, 400 );
$ge->addColor( "black", 0, 0, 0 );
$ge->addColor( "red", 255, 0, 0 );
$ge->addColor( "green", 0, 255, 0 );
$ge->addColor( "blue", 0, 0, 255 );
$gobjs = array();
$gobjs []= new Oval( 100, "red", 50, 50, 150, 150 );
$gobjs []= new Rectangle( 200, "black", 100, 100, 300, 300 );
usort( $gobjs, "zsort" );
foreach( $gobjs as $gobj ) { $gobj->render( $ge ); }
$ge->saveAsPng( "test.png" );
?>
|
此處需要注意兩件事情。首先是我們添加了創(chuàng)建 Oval 和 Rectangle 對象的過程,其中第一個參數(shù)是 z 值。其次是調(diào)用了 usort,它使用了 zsort 函數(shù)來對圖形對象根據(jù) z 值進行排序。
相關(guān)文章
PHP 在5.1.* 和5.2.*之間 PDO數(shù)據(jù)庫操作中的不同之處小結(jié)
今天發(fā)現(xiàn)php5.1.*和php5.2.*在數(shù)據(jù)庫預(yù)編譯代碼執(zhí)行的時候出現(xiàn)差異2012-03-03
php+Mysqli利用事務(wù)處理轉(zhuǎn)賬問題實例
這篇文章主要介紹了php+Mysqli利用事務(wù)處理轉(zhuǎn)賬問題的方法,實例分析了php+mysqli處理事務(wù)的提交與回滾的技巧,需要的朋友可以參考下2015-02-02
php 獲取當(dāng)前訪問的url文件名的方法小結(jié)
php下獲取當(dāng)前訪問的文件名的代碼小結(jié),大家可以根據(jù)需要選擇。2010-02-02
PHP實現(xiàn)表單提交數(shù)據(jù)的驗證處理功能【防SQL注入和XSS攻擊等】
這篇文章主要介紹了PHP實現(xiàn)表單提交數(shù)據(jù)的驗證處理功能,可實現(xiàn)防SQL注入和XSS攻擊等,涉及php字符處理、編碼轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
PHP中unset,array_splice刪除數(shù)組中元素的區(qū)別
php中刪除數(shù)組元素是非常的簡單的,但有時刪除數(shù)組需要對索引進行一些排序要求我們會使用到相關(guān)的函數(shù),這里我們來介紹使用unset,array_splice刪除數(shù)組中的元素區(qū)別吧2014-07-07
PHP生成各種隨機驗證碼的方法總結(jié)【附demo源碼】
這篇文章主要介紹了PHP生成各種隨機驗證碼的方法,結(jié)合具體實例形式總結(jié)分析了php常用的生成驗證碼操作相關(guān)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-06-06

