[TOC] # PHP中GD库的使用 ### GD简介 PHP 不仅限于只产生 HTML 的输出,还可以创建及操作多种不同格式的图像文件。PHP提供了一些内置的图像信息函数,也可以使用GD函数库创建新图像或处理已有的图像。目前GD2库支持GIF、JPEG、PNG和WBMP等格式。此外还支持一些FreeType、Type1等字体库。 * JPEG 是一种压缩标准的名字,通常是用来存储照片或者存储具有丰富色彩和色彩层次的图像。这种格式使用了有损压缩。 * PNG 是可移植的网络图像,对图像采用了无损压缩标准。 * GIF 原义是“图像互换格式”,是一种基于LZW算法的连续色调的无损压缩格式 。 ###### 在PHP中创建一个图像应该完成如下所示的4个步骤: 1. 创建一个背景图像(也叫画布),以后的操作都基于此背景图像。 2. 在背景上绘制图像轮廓或输入文本。 3. 输出最终图形 4. 释放资源 ``` <?php //1. 创建画布 $im = imageCreateTrueColor(200, 200); //建立空白背景 $white = imageColorAllocate ($im, 255, 255, 255); //设置绘图颜色 $blue = imageColorAllocate ($im, 0, 0, 64); //2. 开始绘画 imageFill($im, 0, 0, $blue); //绘制背景 imageLine($im, 0, 0, 200, 200, $white); //画线 imageString($im, 4, 50, 150, 'Sales', $white); //添加字串 //3. 输出图像 header('Content-type: image/png'); imagePng ($im); //以 PNG 格式将图像输出 //4. 释放资源 imageDestroy($im); ?> ``` ### 画布管理 * imagecreate -- 新建一个基于调色板的图像 ``` resource imagecreate ( int x_size, int y_size ) ``` 本函数用来建立空新画布,参数为图片大小,单位为像素 (pixel)。支持256色。 * `imagecreatetruecolor` -- 新建一个真彩色图像 ``` resource imagecreatetruecolor ( int x_size, int y_size ) ``` 新建一个真彩色图像画布 ,需要 GD 2.0.1 或更高版本,不能用于 GIF 文件格式。 * `imagedestroy` -- 销毁一图像 ``` bool imagedestroy ( resource image ) ``` imagedestroy() 释放与 image 关联的内存。 ### 设置颜色 * `imagecolorallocate` -- 为一幅图像分配颜色 ``` 语法:int imagecolorallocate ( resource image, int red, int green, int blue ) ``` imagecolorallocate() 返回一个标识符,代表了由给定的 RGB 成分组成的颜色。red,green 和 blue 分别是所需要的颜色的红,绿,蓝成分。 这些参数是 0 到 255 的整数或者十六进制的 0x00 到 0xFF。 imagecolorallocate() 必须被调用以创建每一种用在 image 所代表的图像中的颜色 ``` $im = imagecreatetruecolor(100, 100); //创建画布的大小为100x100 $red = imagecolorallocate($im, 255, 0, 0); //由十进制整数设置一个颜色 $white = imagecolorallocate($im, 0xFF, 0xFF, 0xFF); // 十六进制方式 ``` * `imagepolygon` -- 画一个多边形 ``` 语法:bool imagepolygon ( resource image, array points, int num_points, int color ) ``` imagepolygon() 在图像中创建一个多边形。points 是一个 PHP 数组,包含了多边形的各个顶点坐标,即 points[0] = x0,points[1] = y0,points[2] = x1,points[3] = y1,以此类推。num_points 是顶点的总数。 * `imagefilledpolygon` -- 画一多边形并填充 ``` 语法:bool imagefilledpolygon ( resource image, array points, int num_points, int color ) ``` imagefilledpolygon() 在 image 图像中画一个填充了的多边形。points 参数是一个按顺序包含有多边形各顶点的 x 和 y 坐标的数组。 num_points 参数是顶点的总数,必须大于 3。 ### 生成图像 * `imagegif` -- 以 GIF 格式将图像输出到浏览器或文件 ``` 语法:bool imagegif (resource image [,string filename] ) ``` * `imagejpeg` -- 以 JPEG 格式将图像输出到浏览器或文件 ``` 语法:bool imagejpeg (resource image [,string filename [, int quality]] ) ``` * `imagepng` -- 以 PNG 格式将图像输出到浏览器或文件 ``` 语法:bool imagepng (resource image [,string filename] ) ``` * `imagewbmp` -- 以 WBMP 格式将图像输出到浏览器或文件 ``` 语法:bool imagewbmp (resource image [, string filename [, int foreground]] ) ``` ### 绘制图像 * `imagefill` -- 区域填充 ``` 语法:bool imagefill(resource image,int x,int y, int color) ``` imagefill() 在 image 图像的坐标 x,y(图像左上角为 0, 0)处用 color 颜色执行区域填充(即与 x, y 点颜色相同且相邻的点都会被填充)。 * `imagesetpixel` -- 画一个单一像素 ``` 语法:bool imagesetpixel ( resource image, int x, int y, int color ) ``` imagesetpixel() 在 image 图像中用 color 颜色在 x,y 坐标(图像左上角为 0,0)上画一个点。 * `imageline` -- 画一条线段 ``` 语法:bool imageline ( resource image, int x1, int y1, int x2, int y2, int color ) ``` imageline() 用 color 颜色在图像 image 中从坐标 x1,y1 到 x2,y2(图像左上角为 0, 0)画一条线段。 * `imagerectangle` -- 画一个矩形 ``` 语法:bool imagerectangle ( resource image, int x1, int y1, int x2, int y2, int col ) ``` imagerectangle() 用 col 颜色在 image 图像中画一个矩形,其左上角坐标为 x1, y1,右下角坐标为 x2, y2。图像的左上角坐标为 0, 0。 * `imagefilledrectangle` -- 画一矩形并填充 ``` 语法:bool imagefilledrectangle ( resource image, int x1, int y1, int x2, int y2, int color ) ``` imagefilledrectangle() 在 image 图像中画一个用 color 颜色填充了的矩形,其左上角坐标为 x1,y1,右下角坐标为 x2,y2。0, 0 是图像的最左上角。 * `imageellipse` -- 画一个椭圆 ``` 语法:bool imageellipse ( resource image, int cx, int cy, int w, int h, int color ) ``` imageellipse() 在 image 所代表的图像中画一个中心为 cx,cy(图像左上角为 0, 0)的椭圆。w 和 h 分别指定了椭圆的宽度和高度,椭圆的颜色由 color 指定。 * `imagefilledellipse` -- 画一椭圆并填充 ``` 语法:bool imagefilledellipse ( resource image, int cx, int cy, int w, int h, int color ) ``` imagefilledellipse() 在 image 所代表的图像中以 cx,cy(图像左上角为 0, 0)为中心画一个椭圆。w 和 h 分别指定了椭圆的宽和高。椭圆用 color 颜色填充。如果成功则返回 TRUE,失败则返回 FALSE。 * `imagearc` -- 画椭圆弧 ``` bool imagearc ( resource image, int cx, int cy, int w, int h, int s, int e, int color ) ``` imagearc() 以 cx,cy(图像左上角为 0, 0)为中心在 image 所代表的图像中画一个椭圆弧。w 和 h 分别指定了椭圆的宽度和高度,起始和结束点以 s 和 e 参数以角度指定。0°位于三点钟位置,以顺时针方向绘画。 * `imagefilledarc` -- 画一椭圆弧且填充 ``` bool imagefilledarc ( resource image, int cx, int cy, int w, int h, int s, int e, int color, int style ) ``` imagefilledarc() 在 image 所代表的图像中以 cx,cy(图像左上角为 0, 0)画一椭圆弧。如果成功则返回 TRUE,失败则返回 FALSE。w 和 h 分别指定了椭圆的宽和高,s 和 e 参数以角度指定了起始和结束点。style 可以是下列值按位或(OR)后的值: IMG_ARC_PIE IMG_ARC_CHORD IMG_ARC_NOFILL IMG_ARC_EDGED IMG_ARC_PIE 和 IMG_ARC_CHORD 是互斥的;IMG_ARC_CHORD 只是用直线连接了起始和结束点,IMG_ARC_PIE 则产生圆形边界。IMG_ARC_NOFILL 指明弧或弦只有轮廓,不填充。IMG_ARC_EDGED 指明用直线将起始和结束点与中心点相连,和 IMG_ARC_NOFILL 一起使用是画饼状图轮廓的好方法(而不用填充)。 ### 在图像中绘制文字 * `imagestring` -- 水平地画一行字符串 ``` 语法:bool imagestring ( resource image, int font, int x, int y, string s, int col ) ``` imagestring() 用 col 颜色将字符串 s 画到 image 所代表的图像的 x,y 坐标处(这是字符串左上角坐标,整幅图像的左上角为 0,0)。如果 font 是 1,2,3,4 或 5,则使用内置字体。 * `imagestringup` -- 垂直地画一行字符串 ``` 语法:bool imagestringup ( resource image, int font, int x, int y, string s, int col ) ``` * `imagechar` -- 水平地画一个字符 ``` 语法:bool imagechar ( resource image, int font, int x, int y, string c, int color ) ``` imagechar() 将字符串 c 的第一个字符画在 image 指定的图像中,其左上角位于 x,y(图像左上角为 0, 0),颜色为 color。如果 font 是 1,2,3,4 或 5,则使用内置的字体(更大的数字对应于更大的字体)。 * `imagecharup` -- 垂直地画一个字符 ``` 语法:bool imagecharup ( resource image, int font, int x, int y, string c, int color ) ``` imagecharup() 将字符 c 垂直地画在 image 指定的图像上,位于 x,y(图像左上角为 0, 0),颜色为 color。如果 font 为 1,2,3,4 或 5,则使用内置的字体。 * `imagettftext` -- 用 TrueType 字体向图像写入文本 ``` 语法 :array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text ) ``` * `imagestring()`用 col 颜色将字符串 s 垂直地画到 image 所代表的图像的 x, y 座标处(图像的左上角为 0, 0)。如果 font 是 1,2,3,4 或 5,则使用内置字体。 # 验证码的绘制和使用 > 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机和人的公共全自动程序。 使用验证码的目的:可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。 验证码是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区)。 验证码的样式也是千奇百态,本节重点讲解使用GD库绘制图像的方式。 ### 设计验证码的步骤 > gd库支持 1. 生成底图 产生一块图片 创建画布 $img=imagecreatetruecolor('x','y') 准备颜色 $bgcolor=imagecolorallocate($img,255,255,255) 填充颜色 imagefill($image,'x','y',$bgcolor) 2. 在图片中生成干扰元素 在底图上显示随机数字 准备字体颜色 可随机 $fontcolor=imagecolorallocate($img,0,0,0); 准备字体大小 $fontsize=10 准备字体内容 $content = rand(0,9) 将内容填充到画布上 imagestring($img,$fontsize,$x,$y,$content,$fontcolor) 注意:控制好字体大小与分布,避免字体重叠或显示不全 为验证码增加干扰元素,干扰的点或线 准备点的颜色 可随机 $pointcolor=imagecolorallocate($img,175,175,175) 画点 imagesetpixel($img,$x,$y,$pointcolor) 增加线干扰元素 准备颜色 可随机 $linecolor=imagecolorallocate($img,90,90,90) 画线 imageline($img,x,y,x,y,$linecolor) 注意:干扰元素一定要控制好颜色,避免喧宾夺主 3. 生成验证内容 生成无规律内容 数字、字母、数字加字母 服务器保存改内容 4. 生成验证码图片 输出 header('content-type:image/png') imagepng($rimg) 销毁资源 imagedestroy($img) 5. 校验验证内容 在服务器记录验证码信息,便于用户输入后做校验 session_start() 必须处于脚本最顶部 多服务器情况,需要考虑集中管理session信息 用户输入对比服务器保存内容 # PHP图片处理(缩放、裁剪、水印、旋转和翻转) ### 图片背景管理 从指定的图片文件或 URL地址来新建一个图像。成功则返回一个图像标识符,失败时返回一个空字符串,并且输出一条错误信息。 由于格式不同,则需要分别使用对应图片背景处理函数。 * 从 PNG 文件或 URL 新建一图像 ``` resource imagecreatefrompng ( string filename ) ``` * 从 JPEG 文件或 URL 新建一图像 ``` resource imagecreatefromjpeg ( string filename ) ``` * 从 GIF 文件或 URL 新建一图像 ``` resource imagecreatefromgif ( string filename ) ``` * 从 WBMP 文件或 URL 新建一图像 ``` resource imagecreatefromwbmp ( string filename ) ``` 其他图像处理函数: * 取得图像宽度 ``` int imagesx ( resource image ) ``` * 取得图像高度 ``` int imagesy ( resource image ) ``` * 取得图像大小、类型等信息 ``` array getimagesize ( string $filename [, array &$imageinfo ] ) ``` ### 图片缩放和裁剪 ``` bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h ) ``` 重采样拷贝部分图像并调整大小,是将一幅图像中的一块正方形区域拷贝到另一个图像中,平滑地插入像素值,因此,尤其是,减小了图像的大小而仍然保持了极大的清晰度。成功时返回 TRUE, 或者在失败时返回 FALSE。其中dst_image 和 src_image 分别是目标图像和源图像的标识符。 ### 添加图片水印 ``` bool imagecopy ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h ) ``` 拷贝图像的一部分(也就是图片合成)。 将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。 ### 图片旋转和翻转 ``` resource imagerotate ( resource $src_im , float $angle , int $bgd_color [, int $ignore_transparent ] ) ``` 用给定角度旋转图像 将 src_im 图像用给定的 angle 角度旋转。bgd_color 指定了旋转后没有覆盖到的部分的颜色。 旋转的中心是图像的中心,旋转后的图像会按比例缩小以适合目标图像的大小——边缘不会被剪去。 如果 ignore_transparent 被设为非零值,则透明色会被忽略(否则会被保留)。 > Have a try 1. 使用GD库实现验证码? 2. 实现在一张图片上添加文字水印。 3. 实现一张图片的等比缩小一半的处理(如a.jpg图片会生成一个s_a.jpg的小图);