上篇文章我们已经学习了一个 GD 库的应用,那就是非常常用的制作验证码的功能。不过在现实的业务开发中,这种简单的验证码已经使用得不多了,大家会制作出更加复杂的验证码来使用。毕竟现在的各种外挂软件已经能够轻松地破解这种简单的图片验证码了。当然,我们也可以简单地对他进行变形,比如使用中文然后按顺序点击之类的,这些都比较简单地就能实现。更复杂的验证码则推荐使用一些开源的库或者api来实现。

今天,我们将继续学习 GD 库的一些常用的应用。依然是通过一些小例子来进行学习,同样也是我们在日常开发中非常常用的一些功能。

生成缩略图

在日常的开发过程中,不管是客户还是我们自己在后台上传的图片,大小可能都不一定是我们需要的尺寸,这个时候缩略图的功能就比较重要了。一般我们会在保留原图的基础上生成对应原图的一张缩略图用于前台统一尺寸页面的展示。

  1. $w = imagesx($im);
  2. $h = imagesy($im);
  3. $imNew = imagecreatetruecolor($w / 2, $h / 2);
  4. imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);
  5. header("Content-type: image/jpg");
  6. imagejpeg($imNew);
  7. imagedestroy($imNew);

上述代码中,我们生成的缩略图是原图的一半大小,使用的就是 imagecopyresized() 这个函数,它的参数依次是新图画布、原图、新图的x和y坐标起始点、原图的x和y坐标起始点、新图的大小、原图的大小。参数比较多,但也比较好理解,就是将原图缩小到指定的大小并放到新的画布上就可以了。

imagesx() 和 imagesy() 函数不要从字面理解为什么 x 、 y 坐标点之类的,它们其实是获得图像句柄文件的宽和高。如果我们输出的是 jpg 格式的图片,还可以指定它的压缩比率。

  1. $w = imagesx($im);
  2. $h = imagesy($im);
  3. $imNew = imagecreatetruecolor($w / 2, $h / 2);
  4. imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);
  5. header("Content-type: image/jpg");
  6. imagejpeg($imNew, null, 10);
  7. imagedestroy($imNew);

也就是 imagejpeg() 函数的最后一个参数,就和 PS 导出图片时的压缩比率一样,如果数字越小,压缩比越高,数字越大,压缩比越低,图片质量也就越好。默认值为 75 ,可以设置从 0 到 100 的压缩比。第二个参数依然是保存图片的路径,我们这里测试的代码还是直接从浏览器输出的,所以我们这里是给的一个 null 。

从图片的画质来看,确实比上一张直接缩小的图片模糊了许多。当然,图片的大小也小了很多。对于网站的优化来说,jpg 图片的压缩比例一般都会在默认值的 75 左右。如果太小就会出现这种过于模糊的情况从而影响用户的体验。具体业务具体分析,需要多大的图片大小还是要根据我们实际的情况来定。

生成指定大小的等比例缩略图

还有一种业务情况是,我们前台的图片展示大小都是一样的,比如商品图片在列表中的显示。这时,很多图片直接压缩可能就会丢失比例,比如我们上传了一张 16:9 的大宽图,而前台列表页的图片位置是 4:3 的图,这里我们就要等比例按照最大宽度或者最大高度进行缩小,同时多出来的部分留白边或者透明边,这时,只要计算一下图片的比例情况就可以了。

  1. $w = imagesx($im);
  2. $h = imagesy($im);
  3. $imNew = imagecreatetruecolor(202, 152);
  4. imagefill($imNew, 0, 0, imagecolorallocate($imNew, 255, 255, 255));
  5. imagerectangle($imNew, 0, 0, 201, 151, imagecolorallocate($imNew, 0, 0, 0));
  6. $sW = 0;
  7. $sH = 0;
  8. if ($w / $h > 200 / 150) {
  9. $q = 200 / $w;
  10. $sH = $h * $q;
  11. $sW = $w * $q;
  12. $sX = 0;
  13. $sY = (150 - $sH) / 2;
  14. } else {
  15. $q = 150 / $h;
  16. $sH = $h * $q;
  17. $sW = $w * $q;
  18. $sX = (200 - $sW) / 2;
  19. $sY = 0;
  20. }
  21. imagecopyresized($imNew, $im, $sX + 2, $sY + 1, 0, 0, $sW, $sH, $w, $h);
  22. header("Content-type: image/jpg");
  23. imagejpeg($imNew);
  24. imagedestroy($imNew);

在测试代码中,我们规定的大小是 200*150 的图片大小,也就是 4:3 的图片规格。而需要操作的图片则是 300*244 的一张不太规范的图片。这时,我们通过计算 宽/高 的比例,来确定是以宽为基准进行缩小还是以高为基准进行缩小。如果原图的宽高比大于我们规定的图片宽高比,则认为是以宽度为基准进行缩小。反之,就是以高度进行缩小。同样地,具体的宽高结果的算法都都是基于对应的比率进行等比例缩小的。同时,我们还要计算图片的位置,要放在居中的位置。最后,再将缩小的大小放入到指定大小的画布中。

我们这段测试代码中的画布多了两个像素,是为了画那个黑色的边框,目的也是为了演示能够看清楚。

可以看到,我们等比例缩放之后是以原图的高为基准进行缩放的,所以图片的两边会出现白边。如果是以宽为基准的,那么图片上下会出现白边。当然,如果原图的比例和我们需要的比例是一样的,就会完整地撑满整个画布。大家可以自己用其它大小的图片测试一下。

图片加水印

除了缩略图之外,加水印的功能也是很多业务开发中必备的功能。直接的文字水印其实就不用多说了,上篇文章中的 imagettftext() 就可以直接加了,只需要给它用 imagecolorallocatealpha() 函数指定一个带透明的颜色就可以了。今天我们主要来讲的是图片水印的添加。

  1. $imNew = imagecreatetruecolor(150, 30);
  2. imagecolortransparent($imNew, imagecolorallocatealpha($imNew, 255, 255, 255, 128));
  3. imagesavealpha($imNew, true);
  4. $font = '../font/msyh.ttf';
  5. imagettftext($imNew, 16, 0, 11, 21, imagecolorallocate($imNew, 255, 255, 255), $font, '硬核项目经理');
  6. if (imagesx($im) > 150 + 10 && imagesy($im) > 60 + 10) {
  7. imagecopy($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 30 - 10, 0, 0, 150, 30);
  8. imagecopymerge($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 60 - 10, 0, 0, 150, 30, 50);
  9. }
  10. header("Content-type: image/jpg");
  11. imagejpeg($im);
  12. imagedestroy($im);

首先,我们通过 imagecolortransparent() 和 imagesavealpha() 指定一个透明画布。然后通过 imagettftext() 生成一张文字图片。注意,这里是图片哦,不是直接添加的文字。

接着,使用 imagecopy() 或 imagecopymerge() 来将水印图片拷贝到原始图片上。这两个函数的区别就是 imagecopymerge() 在图片合并的时候多了一个参数可以指定通道的透明度,也就是说,如果是一张不带透明度的图片可以直接使用这个函数来让图片增加透明的效果。

在添加水印之前的判断是用于判断图片大小是否适合添加水印,如果图片比水印文件还小的话,那么就不要添加水印了,或者再将水印也缩小后再进行添加。

这样,简单地水印添加就完成了。网上其实能找到很多前辈已经封装好的添加水印的类,或者 Composer 中也有很多现成的库,这里只是手写一个简单的效果供大家学习复习。

总结

关于图片 GD 库的功能函数还有很多,但说实话,笔者现在都已经用得不多了。为什么呢?在实际的业务开发中,大家其实都已经习惯使用 oss 、七牛、upyun 之类的云存储了。不管是图片缩放、添加水印,甚至是简单地进行一些 PS 编辑,都非常方便。而且最主要的是不需要再占用我们的服务器存储资源以及带宽资源,何乐而不为呢。像我现在的工作中,程序代码服务器基本上只需要原始的 20G 左右大小就可以了,只是运行代码,不存储上传的文件、图片以及静态资源。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202012/source/3.一起学习PHP中GD库的使用(三).php

参考文档:

https://www.php.net/manual/zh/book.image.php

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

一起学习PHP中GD库的使用(三)的更多相关文章

  1. 一起学习PHP中GD库的使用(二)

    在日常的开发过程中,GD 库最常用的功能就是帮我们对图片进行一些处理,当然,除了处理已有的图片之外,它也可以直接来画图,就像我们最常见的图片验证码.今天的内容主要就是和画图有关,所以最后我们也会做一个 ...

  2. 一起学习PHP中GD库的使用(一)

    又到了一个大家非常熟悉的库了,对于图像图形的处理来说,GD 库是 PHPer 们绕不过去的一道坎.从很早很早的 CMS 或者 Discuz 时代,各类开源软件在安装的时候就会明确地指出 GD 库是它们 ...

  3. 【代码学习】PHP中GD库的使用

    PHP--GD库 ================================================ 一.支持: 需要php支持GD库 二.作用: 验证码.水印.缩放等 三.绘画步骤: ...

  4. php中GD库的简单使用

    在php中需要图像处理的地方GD库会发挥重要的作用,php可以创建并处理包括GIF,PNG,JPEG,WBMP以及XPM在内的多种图像格式,简单的举几个例子: 1.用GD库会创建一块空白图片,然后绘制 ...

  5. php中GD库的一些简单使用

    今天了解了一些GD库的简单使用,现在稍微做一下总结! GD库是什么?,graphic device,图像工具库,gd库是php处理图形的扩展库,gd库提供了一系列用来处理图片的API,使用GD库可以处 ...

  6. (转)php中GD库的配置,解决dedecms安装中GD不支持问题

    了解gd库 在php中,使用gd库来对图像进行操作,gd库是一个开放的动态创建的图像的源代码公开的函数库,可以从官方网站http://www.boutell.com/gd处下载.目前,gd库支持gif ...

  7. PHP中GD库安装

    安装gd库扩展不能像其他扩展安装一样,直接./configure --prefix=/xxx 还需要激活png,jpeg,字库等支持 ./configure --prefix=/xxx --with- ...

  8. PHP中GD库是做什么用的? PHP GD库介绍11111111

    什么是gd库?    gd库是php处理图形的扩展库,gd库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片. 在网站上GD库通常用来生成缩略图或者用来对图片加水印或者对网站数据 ...

  9. 关于织梦系统不支持php中GD库的问题

    大多数人在显成的PHP的CMS时,如织梦CMS,安装的时候不支持GD库,就导致整个网站的验证码不显示,以下是个人对此类问题的解决办法: 1.首先找到wamp的安装目录,找到PHP的文件夹,打开php. ...

随机推荐

  1. 自己动手实现Lua--实现TAILCALL指令

    最近在看<自己动手实现Lua-虚拟机.编译器和标准库>.这是本挺不错的书,通过学习此书能够对Lua语言有比较深刻的理解,此外还可以对如何自己实现一门脚本语言有直观的认识.对于想学习Lua的 ...

  2. CentOS7 快速安装配置mysql8.0

    因为这个项目是两台CentOS7虚拟机,一台当作 MySQL服务器,所以需要配置3306端口公开 参考教学视频:Java2020体系课 22周课 5-2~3 两节课 yum search mysql- ...

  3. Jackson格式化时间和科学计数法问题

    1. 首先如果有自定义   WebMvcConfigurer 或者 WebMvcConfigurationSupport 的,一定不要在上面加 @EnableWebMvc 注解,因为这个注解会覆盖掉s ...

  4. SQL 练习11

    查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息 SELECT * from Student WHERE SId in (SELECT SId from sc WHE ...

  5. 获取访问者真实ip地址?我觉得不可能

    我们真的能通过请求来获取用户真实的ip地址嘛? 答案是不能,如果能,肯定是我学的不够深入,欢迎交流指正. 那么写这篇文章的意义是什么?我们接着往下看. IP地址相当于电脑在网络上的身份证,但事实上IP ...

  6. 接口和包--Java学习笔记

    接口 定义及基础用法 interface定义:没有字段的抽象类 interface person{ void hello(); String getName(); } /*接口本质上就是抽象类 abs ...

  7. 轻松让你的nginx服务器支持HTTP2协议

    目录 简介 HTTP1.1和HTTP2 安装最新的nginx 开启HTTP2支持 添加SSL支持 修改加密算法 Diffie–Hellman对消息进行加密 重定向所有的HTTP请求到HTTPS 启动n ...

  8. wpf Button 动态改变效果

    <Button  x:Name="LearnMore"  Grid.Row="6"  HorizontalAlignment="Left&quo ...

  9. C# 计算文件的MD5

    MD5的作用详见:https://baike.baidu.com/item/MD5/212708?fr=aladdin public static string GetFileMD5(string f ...

  10. linux(5)----------防火墙的配置

    1.安装:    yum install firewalld 2.启动:    service firewalld start 3.检查状态:        service firewalld sta ...