在我之前的教程中,我们讨论了使用PHP GD库进行基本图像操作 。 在该教程中,我简要介绍了该库,并向您展示了如何从文件加载图像或如何在PHP中从头开始创建图像。 之后,我们学习了如何使用GD裁剪,旋转,缩放和翻转图像。 我介绍了imagefilter()
函数,以将不同的滤镜应用于脚本中加载的图像资源。 我还提到了GD中的一些有用函数,例如imagesx()
和imagesy()
来获取加载图像的宽度和高度。
在上一本GD教程结束时,您学习了如何使用该库自动执行基本任务,例如调整目录中所有图像的大小或在保存最终结果之前对其应用灰度等过滤器。 如果您以前从未使用过PHP GD库,那么建议您在阅读此GD入门文章之前先进行阅读。
在本教程中,我们将学习GD中更多有用的功能,以及如何将其用于自动化更多图像处理任务。
使用卷积矩阵处理图像
除了边缘的像素外,图像中的每个像素都被其他八个像素包围。 根据该像素的值和周围像素的值,为每个像素计算诸如模糊或边缘检测之类的效果。 例如,在边缘检测中,颜色的急剧变化意味着我们已经到达图像中某些对象的边缘。 例如,下图中从白色突然变为棕色将表示杯子和桌子的边界。
指定这种过滤器的一种简单方法是使用所谓的“卷积矩阵”。 GD提供imageconvolution( $image, $matrix, $div, $offset)
函数,将3x3卷积矩阵应用于图像资源$image
。
$matrix
参数是一个由三个数组组成的数组,每个数组包含三个浮点值-即它是一个3x3矩阵。 第一个数组的第一个元素乘以左上像素的颜色值。 类似地,将第一阵列的第二元素乘以直接在中心像素顶部的像素的颜色值。 像素的最终颜色是通过将所有这些乘法的结果相加,然后将其除以$div
进行归一化而获得的。 规范化通常将最终颜色值保持在255以下。
如我们所见, $div
参数用作卷积结果的除数以将其值归一化。 另一方面, $offset
参数用于为所有颜色指定偏移值。 您将在以下示例中看到它如何影响最终结果。
卷积示例
这是一些不同的卷积矩阵的列表,我们将它们应用于桌子上杯子的图像。
方块模糊
$box_blur = array([1, 1, 1], [1, 1, 1], [1, 1, 1]);
imageconvolution($im_php, $box_blur, 9, 0);
框模糊通过仅对每个像素及其相邻像素求平均来工作。 我们将除数的值设置为9,因为三个数组中所有元素的总和为9。
锐化
$sharpen = array([0, -1, 0], [-1, 5, -1], [0, -1, 0]);
imageconvolution($im_php, $sharpen, 1, 0);
锐化通过夸大每个像素及其相邻像素之间的差异来工作。 这样可以使边缘更清晰。 在锐化的情况下,除数仍为1,因为三个数组中所有元素的总和为1。
浮雕
$emboss = array([-2, -1, 0], [-1, 1, 1], [0, 1, 2]);
imageconvolution($im_php, $emboss, 1, 0);
浮雕矩阵类似于锐化矩阵,不同之处在于,值的左上角为负,右下角为正,这就是产生压纹效果的原因。 在浮雕卷积矩阵的情况下,所有元素的总和为1,因此我们不必担心规格化或颜色偏移。
边缘检测
$edge_detect = array([-1, -1, -1], [-1, 8, -1], [-1, -1, -1]);
imageconvolution($im_php, $edge_detect, 1, 0);
imageconvolution($im_php, $edge_detect, 1, 255);
边缘检测类似于锐化,但效果更强。 同样,图像的原始值不会比邻域具有更大的权重-这意味着我们只关心边缘,而不关心原始的纯色区域。
使用边缘检测时,所有数组元素的总和为0。这意味着除非颜色发生急剧变化(通常发生在对象的边缘),否则我们将获得的图像大部分为黑色。 通过将offset参数设置为255,可以将大部分为黑色的图像变成白色。
下图显示了所有这些卷积矩阵的结果。
影像复制功能
PHP GD具有很多功能,可以复制图像的一部分,然后调整大小或合并图像。 使用这些功能时,请务必记住,PHP将图像资源的左上角视为其来源。 正的x值会将您带到图像的右边,而正的y值将使您更进一步。
这些功能中最简单的是imagecopy( $dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h)
。 它将源图像复制到目标图像上。 $dst_x
和$dst_y
参数确定复制的图像将粘贴到的左上角。 $src_x
, $src_y
, $src_w
和$src_h
参数确定源图像的矩形部分,该部分将被复制到目标位置。
通过使用imagecreatetruecolor()
从头开始创建图像并将源图像的裁剪矩形复制到其中,可以使用此功能来裁剪图像。 您也可以使用它在图像上添加水印,但是必须记住,使用这种方法,不能根据图像的大小来更改水印的大小。
解决此问题的一种方法是使用imagecopyresized( $dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
函数。 它接受imagecopy()
所有参数和两个附加参数,以确定将源图像复制到的目标区域的大小。
imagecopyresized()
函数并不完美,因为它无法很好地缩放图像。 但是,可以使用imagecopyresampled()
函数获得更好的质量调整大小,该函数接受所有相同的参数。
透明复印
还有两个与复制图像有关的功能,它们会非常有用: imagecopymerge()
和imagecopymergegray()
。
函数imagecopymerge( $dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct)
与imagecopy()
相似,其中附加的$pct
参数确定复制对象的透明度。图片。 值0表示无透明度,值100表示完全透明。 当您不想将主图像的内容完全隐藏在水印后时,这将有很大的帮助。
另一方面, imagecopymergegray()
函数使用last参数将源图像转换为灰度。 如果将其设置为0,则源图像将失去其所有颜色。 如果将其设置为100,则源图像将不受影响。
图像复制示例
以下示例使用imagecopy()
函数将图像的右半部分转换为其底片。 我们已经讨论了其他功能,如imagefilter()
和imagescale()
在此代码段中使用以前的教程 。
$im_php = imagecreatefromjpeg('fish-mosaic.jpg');
$im_php = imagescale($im_php, 800);
$im_php_inv = imagescale($im_php, 800);
$im_width = imagesx($im_php);
$im_height = imagesy($im_php);
imagefilter($im_php_inv, IMG_FILTER_NEGATE);
imagecopy($im_php, $im_php_inv, $im_width/2, 0, $im_width/2, 0, $im_width/2, $im_height);
$new_name = 'fish-mosaic-half-negate.jpg';
imagejpeg($im_php, $new_name);
在这里,我们创建了原始图像的两个副本,每个副本都已缩小为800像素宽。 之后,我们使用imagefilter()
函数创建$img_php_inv
图像资源的负片。 然后使用imagecopy()
函数将此负片图像的右半部分复制到原始图像上。
这是imagecopy()
函数的非常基本的用法。 您可以在下面看到结果。 您还可以将图像分为较小的部分或条纹,以创建更有趣的图像效果。 我们将在下面的代码片段中使用imagecopymergegray()
函数在原始鱼图像中创建更多条纹。
$im_php = imagecreatefromjpeg('fish-mosaic.jpg');
$im_php = imagescale($im_php, 800);
$im_php_bw = imagescale($im_php, 800);
$im_width = imagesx($im_php);
$im_height = imagesy($im_php);
$stripes = 200;
for($i = 0; $i < $stripes; $i++) {
if($i%2 == 0) {
imagecopymergegray($im_php, $im_php_bw, $i*$im_width/$stripes, 0, $i*$im_width/$stripes, 0, $im_width/$stripes, $im_height, 0);
} else {
imagecopymergegray($im_php, $im_php_bw, $i*$im_width/$stripes, 0, $i*$im_width/$stripes, 0, $im_width/$stripes, $im_height, 100);
}
}
imagefilter($im_php, IMG_FILTER_CONTRAST, -255);
imagefilter($im_php, IMG_FILTER_COLORIZE, 250, 0, 0, 100);
$new_name = 'fish-mosaic-stripes.jpg';
imagejpeg($im_php, $new_name);
上面的代码示例使用与前面的示例类似的策略,但是这次我们将图像划分为较小的条纹,这些条纹根据变量$i
的值变为灰度或保持不变。 完成所有复制合并操作后,我们在图像上应用两个滤镜以使条纹突出。
下图显示了这两种功能与不同的图像滤镜一起使用的最终结果。
在图像中嵌入水印或其他信息
一些组织在其图像上添加水印,以便清楚地表明自己拥有该图像。 它还有助于提高品牌知名度,并阻止其他人公然复制图像。 感谢PHP GD,对图像加水印是一项简单的任务。
$im_php = imagecreatefromjpeg('waterfall.jpg');
$watermark = imagecreatefrompng('watermark.png');
$im_width = imagesx($im_php);
$im_height = imagesy($im_php);
$watermark = imagescale($watermark, $im_width/5);
$wt_width = imagesx($watermark);
$wt_height = imagesy($watermark);
imagecopy($im_php, $watermark, 0.95*$im_width - $wt_width, 0.95*$im_height - $wt_height, 0, 0, $wt_width, $wt_height);
$new_name = 'waterfall-watermark.jpg';
imagejpeg($im_php, $new_name);
在上面的代码段中,我们已经使用创建了两个不同的图像资源imagecreatefromjpeg()
用于主图象和imagecreatefrompng()
分别为水印。 我们使用imagesx()
和imagesy()
函数确定主图像的宽度和高度。
并非所有要加水印的图像都具有相同的尺寸。 如果您不根据主图像的尺寸调整水印的大小,则水印看起来可能很奇怪。 例如,一个200像素的水印在1000像素的图像上可能看起来不错,但是对于600像素的图像来说太大了,而在2400像素的图像上看起来太小了。
因此,我们使用imagescale()
函数始终将水印保持在原始图像宽度的五分之一。 然后,我们使用imagecopy()
函数将水印放置在正确的位置。 这是以上代码片段的最终结果。
除了水印之外,您还可以添加其他信息,例如拍摄照片的地点或拍摄时间。
最后的想法
在上一教程中介绍了图像处理的基础知识之后,我们了解了GD库中的其他一些有用功能。 本教程的第一部分讨论了如何使用卷积矩阵在PHP中处理图像。 我还展示了一些卷积矩阵运算的示例,以帮助您了解PHP如何得出不同像素的颜色值。
本教程的第二部分介绍了如何复制和/或调整图像的一部分大小以将其粘贴到其他位置。 当我们想向图像添加一些东西(例如水印或时间戳)时,这非常方便。
尝试使用所有这些功能来创建一些有趣的图像效果!
翻译自: https://code.tutsplus.com/tutorials/php-gd-image-manipulation-beyond-the-basics--cms-31766