本日,我们将连续学习 GD 库的一些常用的运用。依然是通过一些小例子来进行学习,同样也是我们在日常开拓中非常常用的一些功能。
天生缩略图在日常的开拓过程中,不管是客户还是我们自己在后台上传的图片,大小可能都不一定是我们须要的尺寸,这个时候缩略图的功能就比较主要了。一样平常我们会在保留原图的根本上天生对应原图的一张缩略图用于前台统一尺寸页面的展示。
$w = imagesx($im);$h = imagesy($im);$imNew = imagecreatetruecolor($w / 2, $h / 2);imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);header("Content-type: image/jpg");imagejpeg($imNew);imagedestroy($imNew);
上述代码中,我们天生的缩略图是原图的一半大小,利用的便是 imagecopyresized() 这个函数,它的参数依次是新图画布、原图、新图的x和y坐标起始点、原图的x和y坐标起始点、新图的大小、原图的大小。参数比较多,但也比较好理解,便是将原图缩小到指定的大小并放到新的画布上就可以了。

imagesx() 和 imagesy() 函数不要从字面理解为什么 x 、 y 坐标点之类的,它们实在是得到图像句柄文件的宽和高。如果我们输出的是 jpg 格式的图片,还可以指定它的压缩比率。
$w = imagesx($im);$h = imagesy($im);$imNew = imagecreatetruecolor($w / 2, $h / 2);imagecopyresized($imNew, $im, 0, 0, 0, 0, $w / 2, $h / 2, $w, $h);header("Content-type: image/jpg");imagejpeg($imNew, null, 10);imagedestroy($imNew);
也便是 imagejpeg() 函数的末了一个参数,就和 PS 导出图片时的压缩比率一样,如果数字越小,压缩比越高,数字越大,压缩比越低,图片质量也就越好。默认值为 75 ,可以设置从 0 到 100 的压缩比。第二个参数依然是保存图片的路径,我们这里测试的代码还是直接从浏览器输出的,以是我们这里是给的一个 null 。
从图片的画质来看,确实比上一张直接缩小的图片模糊了许多。当然,图片的大小也小了很多。对付网站的优化来说,jpg 图片的压缩比例一样平常都会在默认值的 75 旁边。如果太小就会涌现这种过于模糊的情形从而影响用户的体验。详细业务详细剖析,须要多大的图片大小还是要根据我们实际的情形来定。
天生指定大小的等比例缩略图还有一种业务情形是,我们前台的图片展示大小都是一样的,比如商品图片在列表中的显示。这时,很多图片直接压缩可能就会丢失比例,比如我们上传了一张 16:9 的大宽图,而前台列表页的图片位置是 4:3 的图,这里我们就要等比例按照最大宽度或者最大高度进行缩小,同时多出来的部分留白边或者透明边,这时,只要打算一下图片的比例情形就可以了。
$w = imagesx($im);$h = imagesy($im);$imNew = imagecreatetruecolor(202, 152);imagefill($imNew, 0, 0, imagecolorallocate($imNew, 255, 255, 255));imagerectangle($imNew, 0, 0, 201, 151, imagecolorallocate($imNew, 0, 0, 0));$sW = 0;$sH = 0;if ($w / $h > 200 / 150) { $q = 200 / $w; $sH = $h $q; $sW = $w $q; $sX = 0; $sY = (150 - $sH) / 2;} else { $q = 150 / $h; $sH = $h $q; $sW = $w $q; $sX = (200 - $sW) / 2; $sY = 0;}imagecopyresized($imNew, $im, $sX + 2, $sY + 1, 0, 0, $sW, $sH, $w, $h);header("Content-type: image/jpg");imagejpeg($imNew);imagedestroy($imNew);
在测试代码中,我们规定的大小是 200150 的图片大小,也便是 4:3 的图片规格。而须要操作的图片则是 300244 的一张不太规范的图片。这时,我们通过打算 宽/高 的比例,来确定因此宽为基准进行缩小还是以高为基准进行缩小。如果原图的宽高频年夜于我们规定的图片宽高比,则认为因此宽度为基准进行缩小。反之,便是以高度进行缩小。同样地,详细的宽高结果的算法都都是基于对应的比率进行等比例缩小的。同时,我们还要打算图片的位置,要放在居中的位置。末了,再将缩小的大小放入到指定大小的画布中。
我们这段测试代码中的画布多了两个像素,是为了画那个玄色的边框,目的也是为了演示能够看清楚。
可以看到,我们等比例缩放之后因此原图的高为基准进行缩放的,以是图片的两边会涌现白边。如果因此宽为基准的,那么图片高下会涌现白边。当然,如果原图的比例和我们须要的比例是一样的,就会完全地撑满全体画布。大家可以自己用其它大小的图片测试一下。
图片加水印除了缩略图之外,加水印的功能也是很多业务开拓中必备的功能。直接的笔墨水印实在就不用多说了,上篇文章中的 imagettftext() 就可以直接加了,只须要给它用 imagecolorallocatealpha() 函数指定一个带透明的颜色就可以了。本日我们紧张来讲的是图片水印的添加。
$imNew = imagecreatetruecolor(150, 30);imagecolortransparent($imNew, imagecolorallocatealpha($imNew, 255, 255, 255, 128));imagesavealpha($imNew, true);$font = '../font/msyh.ttf';imagettftext($imNew, 16, 0, 11, 21, imagecolorallocate($imNew, 255, 255, 255), $font, '硬核项目经理');if (imagesx($im) > 150 + 10 && imagesy($im) > 60 + 10) { imagecopy($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 30 - 10, 0, 0, 150, 30); imagecopymerge($im, $imNew, imagesx($im) - 150 - 10, imagesy($im) - 60 - 10, 0, 0, 150, 30, 50);}header("Content-type: image/jpg");imagejpeg($im);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