PHP教程 使用PHP和GD进行图形处理
在我们开始绘图之前,先学一些基础知识,看一下PHP是如何创建一个图像。我们需要做的第一件事就是告诉浏览器它正在得到一个图像和所得到图像的类型:
Header( "Content-type: image/gif");
?>
即然浏览器知道它正在获取一个GIF
图像了,我们可以开始创建图形了。首先我们需要创建一个将用来绘图的空白的画布。ImageCreate函数可以做到这一点。ImageCreate将返
回一个图像的标识符,并且需要告诉函数用象素计算的画布有多大,x(宽度)与y(高度)。
$image = imagecreate(200,200);
?>
现在我们得到了一个200像素乘200像素的可用来绘图的空白画布。下一步是创建将要用在图像中的一些颜色。为了做到这一点我们需要使用
ImageColorAllocate函数,还有颜色的RGB值。ImageColorAllocate
将返回一个我们刚创建的颜色标识。我们将在画布上绘图时使用颜色标识。ImageColorAllocate的工作方式是我们需要为所处理的每一个图像分
配一个颜色 --
所以如果我们创建3个GIF并且在每一个上面使用红色,我们应该分配红色3次(一次为一个GIF)。我将分配一个名为 $maroon的颜色,给定红色值
为100,绿色为0 和兰色为0。同时我将同样创建白色。
$maroon = ImageColorAllocate( $image,100,0,0);
$white = ImageColorAllocate( $image,255,255,255);
?>
即然我们已经得到了颜色,就可以画点什么了。第一件事情要叫的就是将画布白色涂成白色。函数ImageFilledRectangle将在画布上画一个矩形,并且用指定的颜色进行填充。
ImageFilledRectangle( $image,0,0,200,200, $white);
?>
告诉ImageFilledRectangle的第一件事就是(同样用于所有的图像函数)哪一个图像是我们正在处理的
,所以传给它 $image标识。然后它需要知道x和y坐标来开始画矩形(0,0 -- 左上角)和结束矩形的坐标( 200,200 --
画布的右下角)。最后告诉它的事情就是在矩形内填充的颜色,这个例子为 $maroon。现在我们可以开始在白色背景上绘图了。
ImageRectangle( $image,10,10,190,190, $maroon);
ImageFilledRectangle( $image,50,50,150,150, $maroon);
?>
ImageRectangle工作完全与ImageFilledRectangle同样的方式,除了它不使用颜色填充矩形以外。一旦我们画完了,就可以输出图形了 --
ImageGIF( $image);
?>
然后清除我们存在内存中的图像。
ImageDestroy( $image);
?>
这就是我们得到的.然而,它还不是一个要求的图形。
线形图形 为了开始,我们可以创建一个空的200x200像素的画布,并填充为灰色。在这上面可以绘制我们的线段。我们可以为每个办公室分配一个颜色,红色代表伦敦,兰色代表亚特兰大。
现在可以开始取出数据并把它画出来了。需要牢记的一件重要的事就是在画线的时候,ImageLine
要求我们告诉它开始处的x和y坐标还有线的结束坐标。现在如果从一个数据库中抓出数据,将一次只能得到一组坐标。所以可以或者将数据存储在数组中,或使用
一个临时变量来保存前一组坐标。我选择了使用数组。
除了将要绘制的实际坐标之外,还需要知道可达到的最大值(图形的顶部)还有信息列的数目(沿着x轴要画的点的个数)。所以在与数据库连接之后,从数据库中选出了MAX(g_num) 值并将其保存起来为后面使用。
然后选出所以g_team等于'London'的所有记录,并得到返回的记录行数,所以我们将知道有多少要处理的数据列数。从前面的表格中,你可以看到我们将处理6个月或列数据,并且最大值为410。
$columns = 6;
$max = 410;
?>
x值总是最容易处理的 --
它的范围从0到图像的宽度,此处为200。我们将在0处理开始画线并希望在200结束,所以在以 $x=0开始之后,将需要增加 $x值直到
$columns-1次(此处为5)以达到200 --
这样我们要画6次,最后一次将在200处。记住这点以后我们可以创建一个名为 $xincrement的变量,并赋给它200除以( $columns-
1)的值。然后将给出 $x一个开始值0 并且在每一次循环的底部,当从结果集中抓取记录行时,我们可以给 $x增加 $xincement。
$xincrement = bcdiv(200, $columns-1,0);
?>
bcdiv用第二个参数除以第一个参数,并且返回根据第三个参数所指定的小数位数的值。为了使用BCMath函数,你需要在Unix下将其编译到PHP
中,但是Windows版本已经将其编译进去了。README.BCMATH在PHP源代码的根目录中,它将解释在哪和如何做。
y值将与 $max数值成比例,所以我们所能做的就是用 $max来除g_num得到比例的小数值,然后乘以200 --图像的高度。
$y = bcmul(bcdiv( $salesRow[0], $max,2),200,2);
?>
$salesRow[0]是当前行的g_num值,除上 $max,并且结果定为小数部分为2位。然后使用bcmul将结果与200相乘。
然后可以做的就是在整个数组中循环,使用当前元素作为线的开始,当前元素 1作为线的结束。因为最后一个元素将永远不会是一行的开始,我们必需将循环减1,所以将当小于或等于 $columns-1 时循环改为小
于 $columns-1时循环。
让我们看一下迄今为止的代码:
// 发送头信息和创建初始的空白画布
Header( "Content-type: image/gif");
$image = imagecreate(200,200);
// 分配一些颜色
$red = ImageColorAllocate( $image,255,0,0);
$blue = ImageColorAllocate( $image,0,0,255);
$white = ImageColorAllocate( $image,255,255,255);
$grey = ImageColorAllocate( $image,200,200,200);
// 创建一个初始的灰色矩形用于绘图
ImageFilledRectangle( $image,0,0,200,200, $grey);
// 连接mysql服务器并选择数据库
$connect = mysql_connect("","root","");
mysql_select_db("graphing", $connect);
// 找到结果集中的最大数值
$sql = "SELECT MAX(g_num) FROM sales";
$maxResult = mysql_query( $sql, $connect);
$max = mysql_result( $maxResult,0,0);
// 得到伦敦的结果集
$sql = "SELECT g_num FROM sales WHERE g_team='London' ORDER BY g_month";
$salesResult = mysql_query( $sql, $connect);
// 找到返回多少列,就是'columns'的数值
$columns = mysql_num_rows( $salesResult);
// $x每次增加多少量?
$xincrement = bcdiv(200, $columns-1,0);
$x=0;
// $i 将记录行的数值
$i=0;
// 在我们所有的数据行中循环
while( $salesRow=mysql_fetch_array( $salesResult))
{
// 象上面所讨论地计算y的坐标值
$y = bcmul(bcdiv( $salesRow[0], $max,2),200,2);
// 在 $points数组中增加值
$points[ $i][0] = $x;
$points[ $i][1] = $y;
// 增加 $x的值用 $xincrement
$x = $xincrement;
// 增加 $i
$i ;
}
// 现在我们在 $points数组中循环,此时 $i小于 $columns-1
for( $i=0; $i< $columns-1; $i )
{
// 我们传递 $points[ $I][0] 作为第一个x坐标, $points[ $I][1] 为第一个y坐标
// $points[ $I 1][0],
$points[ $I 1][1] 将是下一个x,y坐标集
ImageLine( $image, $points[ $i][0], $points[ $i][1], $points[ $i 1][0], $points[ $i 1][1], $red);}
// 输出GIF给浏览器 并且释放内存
ImageGIF( $image);
ImageDestroy( $image);
?>
这样将给出我们如下的结果:
它既不正确也很气人。问题在于我们是按传统的x和y坐标方法处理的,这种方法是从左下角向外发散的。Image函数的坐标系统是从左上角发散的,所以这时我们的x位置是正确的,我们的y位置弄反了。
我们需要做的就是修改确定y位置的代码以便按相反的方式工作 -- 改变行
ImageLine( $image, $points[ $i][0], $points[ $i][1], $points[ $i 1][0], $points[ $i 1][1], $red);
?>
变成读取:
ImageLine( $image, $points[ $i][0],200- $points[ $i][1], $points[ $i 1][0],200-
$points[ $i 1][1], $red);
?>
我们将得到图形:
src="">
现在我们需要做的是加入一条线,它是将亚特兰大的数据进行了图形化。
$sql = "SELECT g_num FROM sales WHERE g_team='Atlanta' ORDER BY g_month";
$salesResult = mysql_query( $sql, $connect);
$columns = mysql_num_rows( $salesResult);
$xincrement = bcdiv(200, $columns-1,0);
$x=0;
$i=0;
while( $salesRow=mysql_fetch_array( $salesResult)) {
$y = bcmul(bcdiv( $salesRow[0], $max,2),200,2);
$points[ $i][0] = $x;
$points[ $i][1] = $y;
$x = $xincrement;
$i ;
}
for( $i=0; $i< $columns-1; $i ) {
ImageLine( $image, $points[ $i][0],200- $points[ $i][1], $points[ $i 1][0],200- $points[ $i 1][1], $blue);
}
?>
src="">
我们用在这个例子中的数据是静态的,在以后的部分我们将看一下如何处理动态数据,并且看一下在图表中增加一些轴线和标签。