【php】图片处理&开发验证码

发布于:2022-11-03 ⋅ 阅读:(510) ⋅ 点赞:(0)

注:最后有面试挑战,看看自己掌握了吗

🍃博主昵称:一拳必胜客
🌸博主寄语:欢迎点赞收藏关注哦,一起成为朋友一起成长;
 特别鸣谢:木芯工作室
特别鸣谢:木芯工作室 、Ivan from Russia


图像处理

处理图片的场景很多:

生成验证码
图片缩放
图片水印
密保口令卡
柱状图
... ...

在这里插入图片描述

图片处理 gd2配置文件修改

开篇知道了图像处理的主要作用,功能和未来使用的地方。

学习图像处理重点就是学习PHP的GD系统的函数

P它也可以创建和处理包括 GIF, PNG, JPEG, WBMP 以及 XPM 在内的多种格式的图像。更加方便的是,PHP可以直接将图像数据流输出到浏览器。要想在PHP中使用图像处理功能,你需要连带GD库一起来编译 PHPGD 库和PHP可能需要其他的库,这取决于你要处理的图像格式。

你可以使用 PHP 中的图像函数来获取下列格式图像的大小: JPEG, GIF, PNG, SWF, TIFF 和 JPEG2000。

查看我们当前的机器是否安装了GD扩展,我们可以写我们第一天学习到的第一句话:

<?php phpinfo(); ?>

看下图,如果存在了gd这个选项,就说明我们当前机器支持GD来处理图像:

6.png

如果没有看到,也没有搜索到。可以按照如下步骤打开gd来处理图像

1.打开php.ini(在文件上传这一章已有说明)

2.在 Windows 中,需要将GD2的DLL文件php_gd2.dll作为一个扩展包含在 php.ini 中。修改;extension = php_gd2.dll,将前面的分号去掉

3.重新启动apache服务器

4.再次执行phpinfo尝试查看是否存在gd扩展

用图片处理函数画一张图

一起来看看下面有一张图:

7.png

我们该怎么把这张图给画出来呢。

1.画图

2.准备好画这张图需要的颜色

3.填充背景颜色

4.画两条对角线

5.在上面画一个圆

6.在圆上面画一个矩型

7.保存图片

8.销毁资源

一、我们根据这张图推出出来步骤。我们来分析需要使用到的函数:

//使用imagecreate函数创建图片,返回资源
$img = imagecreate(500,500);

二、图片创建完成我们需要向图片资源填加颜色,需要使用到函数

$颜色变量 = imagecolorallocate ( resource $图片资源 , int $红 , int $绿 , int $蓝 )

红、绿、蓝是计算机里面操作图片的三个基本色。由这三个颜色来组合成我们肉眼所看到的所有颜色。

因此 imagecolorallocate 先输入图片资源,操作这个资源。为这个图片资源准备颜色。

就相当于在画画的时候,先把画布准备好,再准备颜料。

根据这张图,我们需要准备出来的颜色有:

1.绿

2.蓝

3.黑

4.棕

按照计算机的配色原则分配的话,我们下面的颜色分配的代码就要写成下面的样子:

//红
$red = imagecolorallocate($img, 255, 0, 0);
//绿
$green = imagecolorallocate($img, 0, 255, 0);
//蓝
$blue = imagecolorallocate($img, 0, 0, 255);
//棕
$yellow = imagecolorallocate($img, 121, 72, 0);
这中图片中需要用到的几个颜色的色值。

三、 将颜色添加到背景进行填充

imagefilledrectangle ( resource $图片资源 , int $点1x轴, int $点1y轴 , int $点2x轴 , int $点2y轴 , int $color )

这个函数需要涉及到几何的一点点知识。

1.一个点由x 坐标和y 坐标组成一个点

2.两个点可以组成一个直线

3.这条线如果不是水平或者垂直的线可以组成一个矩形

如下图:

document_2015-09-19_55fd0d5be46bb.png

点1和点2,可以变成一个矩形。因此,我们输出两个坐标点,可以对画布进行填充。

如果要填充整个画布的话:

点1 为x轴为画布的0位置,点1的y轴也为画布的0位置。

点2 为x轴为画布的500位置,点2的y轴也为画布的500位置。

四、画两条对角线

画一条对角线,对角线是红色。

第一条对角线的坐标为0和0,500和500
第二条对角线的坐标为500和0,0和500

imageline($img, 0, 0, 500, 500, r e d ) ; i m a g e l i n e ( red); imageline( red);imageline(img, 500, 0, 0, 500, $blue);
五、在上面画一个圆

bool imagefilledellipse ( resource $图片资源 , int $圆心x , int $圆心y , int $圆的宽 , int $圆的高 , int $圆的颜色 )
imagefilledellipse($img, 250, 250, 200, 200, $yellow);
操作这个资源,写上圆心的坐标。然后写上长和宽。如果长宽一致为正圆,不一致则为椭圆。

六、在圆上面画一个矩型

imagefilledrectangle($img, 200, 200, 300, 300, $blue);

这个我们在上面一个中讲过,我们就不细说了。

七、保存图片

bool imagejpeg ( resource $image [, string $filename])

八、销毁图片资源

imagedestroy($img);

我们来看一下最终组合出来的代码:

<?php
//创建图片
$img = imagecreatetruecolor(500, 500);

//分配颜色
$red = imagecolorallocate($img, 255, 0, 0);

$green = imagecolorallocate($img, 0, 255, 0);

$blue = imagecolorallocate($img, 0, 0, 255);

$pur = imagecolorallocate($img, 255, 0, 255);

$yellow = imagecolorallocate($img, 121, 72, 0);


//填充背景
imagefilledrectangle($img, 0, 0, 500, 500, $green);

//画对角线
imageline($img, 0, 0, 500, 500, $red);
imageline($img, 500, 0, 0, 500, $blue);

//画圆
imagefilledellipse($img, 250, 250, 200, 200, $yellow);

//圆中间画矩形
imagefilledrectangle($img, 200, 200, 300, 300, $blue);


//保存图片,图片名为haha.jpg
imagejpeg($img, 'haha.jpg');

//销毁资源
imagedestroy($img);

?>

开发验证码(生成验证码)

通过上一节,我们已经很好的掌握了图像处理的精髓。

通过我们所掌握的知识。进行一些简单的扩展,我们就可以写出:网上最常用的一个小东西——验证码。

验证码是为了防止机器自动注册、机器自动刷票最常用的手段之一。

我们来看一下验证码的效果:

在这里插入图片描述

我们根据上面的效果来推理实现的过程。

实现过程:

1.生成指定宽高的画布

2.准备好字好需要生成的字符串

3.每次执行,让背景填充随机的颜色(浅色系)

4.在画布上画上随机的干扰元素(随机点、随机线、随机弧形等均可,但不可过份影响用户的视觉)

5.写上4个文字

6.输出header头,告知浏览器按照某类型显示

7.输出图像

8.销毁图像资源

上面的步骤把实现验证码的每一步都讲清楚了。下面我们来根据这个过程来推理实现。

第一步、创建画布

$img = imagecreate($width, $height);

我们可以定义一个自定义的宽和高。做一个函数将,可以通过函数传入宽和高。这样,可以修改验证码图像的大小。

function check_code($width = 100, $height = 50) {
    $img = imagecreate($width, $height);
}

第二步、生成验证码显示的文字

验证码的文字通常有数字、字母。而为了区别验证码字符。我们可以用0-9A-Za-Z。但是0和o,l和I有的时候区分不清楚。我们如果不需要处理,可以想办法去除掉:

方案一:

环4个ascii码,而ascii码,而chr或者sprintf(‘%c’,第二个参数传ascii码) 将对应的字符转为指定的字符。

 for ($i = 0; $i < $num; $i++) {
        $rand = mt_rand(0, 2);
        switch ($rand) {
            case 0:
                $ascii = mt_rand(48, 57); //0-9
                break;
            case 1:
                $ascii = mt_rand(65, 90); //A-Z
                break;
            case 2:
                $ascii = mt_rand(97, 122); //a-z
                break;
        }
        //chr()
        $string .= sprintf('%c', $ascii);
    }

方案二:

方案一对很多人来说有点复杂,很多人理解不了ascci码。有没有更简单的方案呢。单然有。我可以准备好字符,然后用str_shuffle打乱字符后使用substr进行截取

//没有0,i,l,o
$str = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789';
$str = str_shuffle($str);
$string = substr($str,0 ,3);

三、 每次执行,让背景填充随机的颜色(浅色系)

文字是深色的看得清楚,而背景是潜色的。

背景的RGB颜色表示通常是这样的,RGB颜色是三个色值,这三个色值都是从0-255。

而:

0-120 低数值是深色系。
130 - 255 通常为浅色系。

使用到图片颜色的地方挺多的。因此,我可以定义分配颜色的功能:

//浅色的背景函数
function randBg($img) {
    return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255));
}
//深色函数,深色的字或者点这些干 扰元素
function randPix($img) {
    return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
}

四、在画布上画上随机的干扰元

我们可以随机的在图片中画上50个像素点。最小的位置为0,0。最大的位置为最大的宽或者最大的高。

然后使用mt_rand(0,最大宽)、mt_rand(0,最大高)。再使用randPix针对我们创建的画布来分配颜色。

   //画干扰元素
    for ($i = 0; $i < 50; $i++) {
        imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img));
    }

五、写上4个文字

$string是一个字符串,字符串$string[0]为字符的第一个字符,依此类类推。

因此,我可在使用imagechar函数在图像中写入文字

而写入文字的x,y的坐标我们可以用一个公式推倒出来。

X位置 = 图像宽/字符个数(4) * 循环次数。
得到的结果取整后再乘以每次循环的次数。假设图像为100个宽度,那么:第一次写在0的位置,第二次为 25,第三次为50,第四次为75。

Y位置 = mt_rand(0,图像高- 15)。

我们可以推导出下面的代码,就可以写出对应的文字了:

   for ($i = 0; $i < $num; $i++) {
        $x = floor($width / $num) * $i;
        $y = mt_rand(0, $height - 15);
        imagechar($img, 5, $x, $y, $string[$i], randPix($img));
    }

六、输出header头,告知浏览器按照某类型显示

我们知道图像类型输出函数都有:imagejpeg,imagepng,imagegif等特点

而图像的mime类型为image/jpeg,image/png,image/gif等。

因此,我们可以声明一个变量:

$imagetype = 'jpeg';
$imagetype = 'png';
$imagetype = 'gif';

出header类型的时候执行

$header = 'Content-type:image/' . $imagetype;

执行函数输出的可以拼接出一个变量函数:

$func = 'image' . $type;

如果我们的系统支持个类型,则使用function_exists检测函数是否存在。存在则系统支持该类型,不存在则不支持该类型。

所以代码可以写成这样:

   $func = 'image' . $type;
    $header = 'Content-type:image/' . $type;
    if (function_exists($func)) {
        header($header);
        //变为了imagejpeg等
        $func($img);
    } else {
        echo '图片类型不支持';
    }

八、销毁资源,返回字符

以后在验证的时候,大家需要把验证码显示出来。并且,用户输出的验证字符还需要与图像中的验证字符匹配

所以要将验证字符返回回来,供以后保存使用

   imagedestroy($img);
    return $string;

我们来看一下全部的准备完成的PHP函数文件,我们将上面的代码封装成一个统一的函数供大家来学习使用:

<?php

check_code();

function check_code($width = 100, $height = 50, $num = 4, $type = 'jpeg') {

   $img = imagecreate($width, $height);
   $string = '';
   for ($i = 0; $i < $num; $i++) {
       $rand = mt_rand(0, 2);
       switch ($rand) {
           case 0:
               $ascii = mt_rand(48, 57); //0-9
               break;
           case 1:
               $ascii = mt_rand(65, 90); //A-Z
               break;

           case 2:
               $ascii = mt_rand(97, 122); //a-z
               break;
       }
       //chr()
       $string .= sprintf('%c', $ascii);

   }
   //背景颜色
   imagefilledrectangle($img, 0, 0, $width, $height, randBg($img));

   //画干扰元素

   for ($i = 0; $i < 50; $i++) {

       imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img));

   }
   //写字
   for ($i = 0; $i < $num; $i++) {
       $x = floor($width / $num) * $i + 2;
       $y = mt_rand(0, $height - 15);

       imagechar($img, 5, $x, $y, $string[$i], randPix($img));

   }

   //imagejpeg

   $func = 'image' . $type;

   $header = 'Content-type:image/' . $type;

   if (function_exists($func)) {
       header($header);
       $func($img);
   } else {

       echo '图片类型不支持';
   }
   imagedestroy($img);
   return $string;

}
//浅色的背景
function randBg($img) {
   return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255));
}
//深色的字或者点这些干 扰元素
function randPix($img) {
   return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
}

?>

图像缩放和裁剪技术

上一章我们学习了图片的水印技术,水印技术和我们这一章要学习到的缩放、裁剪技术基本一致,只不过使用的函数发生了一点点变化。

常用的两个函数如下:

函数名	函数说明
imagecopyresampled	重采样拷贝部分图像并调整大小
imagecopyresized	拷贝部分图像并调整大小

我们来看看这两个函数,这两个函数用起来不难。就是参数略有些复杂。并且来完成图像的缩放或者裁剪:

bool imagecopyresampled ( resource $目标图 , resource $来源图 , 
int $目标开始的x位置 , int $目标开始的y位置 , 
int $来源开始的x位置 , int $来源开始的y位置 , 
int $目标图片的宽 , int $目标图片的高, int $来源图片的宽 , int $来源图片的高 )

请注意,上下两个图片的参数都是一样的

bool imagecopyresized ( resource $目标图 , resource $来源图 ,
 int $目标开始的x位置 , int $目标开始的y位置 , 
 int $来源开始的x位置 , int $来源开始的y位置 ,
  int $目标图片的宽 , int $目标图片的高, int $来源图片的宽 , int $来源图片的高 )

图片缩放和裁剪的方法都是一样的,不同的是拷贝时拷贝的是整张图片还是部份部片。

操作方式说明:

从来源图片的开始点(x,y)起,指定的宽高的大小图片。放至到目标图片的起点(x,y),指定宽高大小的图片中。

一、**缩放图片,**我们将操作步骤化

1.打开来源图片

2.设置图片缩放百分比(缩放)

3.获得来源图片,按比调整大小

4.新建一个指定大小的图片为目标图

5.将来源图调整后的大小放到目标中

6.销毁资源

缩放:

<?php

//打开来源图片
$image = imagecreatefrompng('fbb.png');


//定义百分比,缩放到0.1大小
$percent = 0.1;


// 将图片宽高获取到
list($width, $height) = getimagesize('fbb.png');

//设置新的缩放的宽高
$new_width = $width * $percent;
$new_height = $height * $percent;

//创建新图片
$new_image = imagecreatetruecolor($new_width, $new_height);

//将原图$image按照指定的宽高,复制到$new_image指定的宽高大小中
imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

header('content-type:image/jpeg');
imagejpeg($new_image);
?>

二、裁剪图片,我们将操作步骤化:

1.打开来源图片和目标图片

2.截取来源图片中的点,设置宽高。放至到目标图片中。(裁剪)

3.保存图片输入

4.销毁资源

坐标和宽高我们都清楚了我们开始按照函数的用法来,使用代码来操作图片:

<?php
 $dst = imagecreatefrompng('hsq.png');
 $src = imagecreatefrompng('du.png');
 imagecopyresized($dst, $src, 281, 71, 407, 154, 132, 160, 80, 90);
 header('content-type:image/jpeg'); 
imagejpeg($dst); 
imagedestroy($dst);
 imagedestroy($src);
 ?>
本文含有隐藏内容,请 开通VIP 后查看