在我之前的教程中,我们讨论了使用 PHP GD 库的基本图像处理。在该教程中,我简要介绍了该库,并向您展示了如何从文件中加载图像或在 PHP 中从头开始创建它们。之后,我们学习了如何使用 GD 裁剪、旋转、缩放和翻转图像。我介绍了imagefilter()
将不同过滤器应用于脚本中加载的图像资源的功能。我还提到了 GD 中的一些有用函数,比如imagesx()
获取imagesy()
加载图像的宽度和高度。
使用卷积矩阵处理图像
图像复制功能
图像的 Base64 编码和解码
在图像中嵌入水印或其他信息
在我上一个 GD 教程结束时,您学习了如何使用该库自动执行基本任务,例如调整目录中所有图像的大小或在保存最终结果之前对其应用灰度等过滤器。如果您以前从未使用过 PHP GD 库,我建议您在阅读这篇文章之前先阅读那篇 GD 介绍性文章。
在本教程中,我们将了解 GD 中更多有用的功能,以及如何使用它们来自动化更多的图像处理任务。
1、使用卷积矩阵处理图像
除了边缘的像素外,图像中的每个像素都被其他八个像素包围。根据每个像素的值和周围像素的值计算模糊或边缘检测等效果。例如,在边缘检测中,颜色的急剧变化意味着我们已经到达图像中某个对象的边缘。例如,下图中从白色突然变为棕色将表示杯子和桌子的边界。
指定这种过滤器的一种简单方法是使用所谓的“卷积矩阵”。GD 提供了imageconvolution( $image, $matrix, $div, $offset)
将 3x3 卷积矩阵应用于图像资源的功能$image
。
该$matrix
参数是一个由三个数组组成的数组,每个数组包含三个浮点值——即它是一个 3x3 矩阵。第一个数组的第一个元素乘以左上角像素的颜色值。类似地,第一个数组的第二个元素乘以直接位于中心像素顶部的像素的颜色值。像素的最终颜色是通过将所有这些乘法的结果相加然后除以$div
进行归一化而获得的。归一化通常将最终颜色值保持在 255 以下。
正如我们所见,该$div
参数被用作卷积结果的除数以对其值进行归一化。$offset
另一方面,该参数用于指定所有颜色的偏移值。您将在下面的示例中看到它如何影响最终结果。
1-1、卷积示例
这是我们应用于桌子上杯子图像的一些不同卷积矩阵的列表。
框模糊
$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); |
锐化通过夸大每个像素与其相邻像素之间的差异来工作。这使边缘更清晰。在sharpen的情况下,除数仍然是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。这意味着我们将得到的图像大部分是黑色的,除非颜色发生急剧变化,这通常发生在物体的边缘。通过将偏移参数设置为 255,可以将大部分黑色图像变为白色。
下图显示了所有这些卷积矩阵的结果。
1-2、图像复制功能
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()
但是,您可以使用接受所有相同参数的函数获得更好的质量调整大小。
1-3、透明复印
还有两个与复制图像相关的功能,您会发现它们非常有用: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()
另一方面,该函数使用最后一个参数将源图像转换为灰度。如果设置为 0,源图像将失去所有颜色。如果设置为 100,源图像将不受影响。
1-4、图像复制示例
以下示例使用该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
。完成所有复制合并操作后,我们在图像上应用两个滤镜以使条纹突出。
下图显示了这两个函数结合不同图像过滤器的最终结果。
2、图像的 Base64 编码和解码
在处理图像时,您可能会遇到图像数据需要从 Base64 格式解码或编码到其中的情况。GD 库中没有直接的函数来完成此任务。但是,您可以使用其他一些 PHP 函数轻松完成此操作。
PHP GD 中没有返回图像数据的函数。但是,像imagejpeg()
、imagepng()
和等函数imagegif()
能够将图像输出到浏览器或文件。我们可以使用一些输出控制函数来捕获它们的输出,例如ob_get_contents()
. 这是一个将 JPEG 图像转换为 Base64 数据的示例。
<?php $img = imagecreatefromjpeg( 'frog.jpg' ); ob_start(); imagejpeg( $img ); $image_data = ob_get_contents(); ob_end_clean(); $image_data_base64 = base64_encode ( $image_data ); // Outputs: /9j/4AAQSkZJRgABAQEAYABgAAD//gA+Q1JFQVR.... echo $image_data_base64 ; ?> |
imagecreatefromjpeg()
首先,我们使用该函数从我们的图像文件中获取一个新的图像对象。之后,我们使用该ob_start()
函数打开输出缓冲。然后该imagejpeg()
函数输出原始图像流,因为我们没有将文件名作为第二个参数传递。然后将此捕获的数据存储在$image_data
变量中,使用ob_get_contents()
该变量返回输出缓冲区的内容。然后使用该base64_encode()
函数将原始图像数据转换为 Base64 格式。
PHP GD 带有一个名为的函数,该函数imagecreatefromstring()
将从给定字符串中的图像流创建一个新图像。假设您有 Base64 编码字符串中的图像数据。您可以使用以下代码将其保存为使用 PHP 的图像文件。
<?php $image_data = base64_decode ( $image_data_base64 ); $img = imagecreatefromstring( $image_data ); imagejpeg( $img , 'profile.jpg' ); imagedestroy( $img ); ?> |
我们首先在 的帮助下解码 Base64 字符串base64_decode()
以获取原始图像数据流。然后将此流传递给imagecreatefromstring()
函数以取回我们的图像。之后,您可以简单地使用该imagejpeg()
功能将图像保存为 JPEG 文件。
3、在图像中嵌入水印或其他信息
一些组织会在其图像中添加水印,以表明他们拥有该图像。它还有助于品牌识别,并阻止其他人公然复制图像。感谢 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()
函数确定主图像的宽度和高度。
并非所有要添加水印的图像都具有相同的尺寸。如果您不根据主图像的尺寸调整水印的大小,它可能看起来很奇怪。例如,200px 的水印在 1000px 的图像上可能看起来不错,但对于 600px 宽的图像来说它太大了,而在 2400px 宽的图像上它可能看起来太小了。
因此,我们使用该imagescale()
功能将水印始终保持在原始图像宽度的五分之一。然后我们使用该imagecopy()
函数将水印放置在正确的位置。这是上述代码片段的最终结果。
除了水印,您还可以添加其他信息,例如照片的拍摄地点或照片的拍摄时间。
最后的想法
在我们之前的教程中介绍了图像处理的基础知识之后,我们了解了 GD 库中的一些其他有用的函数。本教程的第一部分讨论了我们如何使用卷积矩阵在 PHP 中处理图像。我还展示了卷积矩阵运算的一些示例,以帮助您了解 PHP 如何得出不同像素的颜色值。
本教程的第二部分解释了如何复制和/或调整图像的一部分以将其粘贴到其他地方。当我们想在图像中添加一些东西(如水印或时间戳)时,这很方便。
尝试使用所有这些功能来创建一些有趣的图像效果!
发表评论 取消回复