设为首页 收藏本站
查看: 983|回复: 0

[经验分享] PHP之图形处理

[复制链接]

尚未签到

发表于 2015-8-24 16:24:07 | 显示全部楼层 |阅读模式
  图形处理
  
  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、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-103663-1-1.html 上篇帖子: Eclipse用XDebug调试PHP程序 下篇帖子: windows2003+iis6.0+php(fastcgi)5.3+wincache+memcached
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表