PHP-GD系列:制作验证码、生成缩略图、添加水印、图片特效

一、验证码的制作流程

1.创建画布资源

  • 创建新的画布:imagecreate(宽,高):创建基于调色板的画布,支持颜色少
           imagecreatetruecolor(宽,高):创建正彩色画布,支持颜色多
  • 基于已有图像创建画布 imagecreatefromjpeg(图片地址),imagecreatefrompng/gif

2.操作画布

  • 设置画布背景颜色:
    1.分配颜色:RGB模式,格式:变量=imagecolorallocate(画布资源,颜色R,颜色G,颜色B)
    2.填充画布:imagefill(画布资源,位置X,位置Y,颜色),左上角的坐标0,0;右下角的坐标width-1,height-1
  • 将字符串写到画布上:
    1.随机抽取文字
    2.随机设置颜色
    3.将文字放在画布上:imagettftext (画布资源 ,字体大小, 角度, 位置x,位置y,颜色 ,字体, 文字内容 )
    4.将验证码连接后存入session中,以便后续验证
  • 加上干扰元素:
    1.加像素点(200个):imagesetpixel ( 画布资源 , 位置x, 位置y ,颜色)
    2.加干扰直线(5条):imageline (画布资源,起始位置x , 起始位置y ,结束位置x , 结束位置y , 颜色)

3.导出 && 销毁

  • 导出:imagepng/gif/jpeg(画布资源[,图片地址,图片质量])
    如果没有图片地址的参数,则表示该图片直接在浏览器输出,需要告知浏览器输出图片header(‘content-type:image/png’);
    图片质量:0~100,100质量最好
  • 销毁:imagedestroy(画布资源)

4.前端

  • 显示图片及点击更换验证码:
    <img src=“code.php” οnclick=“this.src=‘code.php?’+Math.random()”>
    加上Math.random()的参数可以防止服务器缓存,每次点击都是新的
  • 输入框输入验证码,ajax请求,重新渲染页面,返回结果
    如下图
    验证码图片
    github :https://github.com/YY-FS/Study/tree/master/GD/CAPTCHA

二、验证码的制作代码

1.PHP制作验证码

<?php
class Code
{
    private $str = "023456789ABCDEFGHJKMNOPQRSTUVWXYZ";//验证码的字符,去除1,i,l,因为有点像
    private $len, $width, $height;                     //定义验证码的字符数量,宽,高
    private $im;                                       //画布资源

    public function __construct($len = 4, $width = 30, $height = 50)
    {
        $this->width = $width;      //初始化成员变量
        $this->height = $height;
        $this->len = $len;
        session_start();            //开启session
        $this->getCode();           //获得验证码图片
    }

    /**
     * 获得验证码图片
     */
    private function getCode()
    {
        //1.创建画布资源
        $this->createPic();
        //2.创建背景颜色
        $gray = $this->createColor(176, 196, 222);
        imagefill($this->im, 0, 0, $gray);
        //3.加上验证码字
        $this->addString();
        //4.加干扰元素
        $this->addPix();
        $this->addLine();
    }

    /**
     * 4.加干扰元素:加像素点
     */
    private function addPix()
    {
        for ($i = 0; $i < 200; $i++) {
            $color = $this->createColor(mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); //随机获取颜色,取比较深的
            //加像素点
            imagesetpixel($this->im, mt_rand(1, ($this->width * $this->len) - 1), mt_rand(1, $this->height - 1),
                $color);
        }
    }

    /**
     * 4.加干扰元素:加线 
     */
    private function addLine()
    {
        for ($i = 0; $i < 5; $i++) {
            $color = $this->createColor(mt_rand(0, 180), mt_rand(0, 180), mt_rand(0, 180));
            //画线
            imageline($this->im, mt_rand(1, ($this->width * $this->len) - 1), mt_rand(1, $this->height - 1),
                mt_rand(1, ($this->width * $this->len) - 1), mt_rand(1, $this->height - 1), $color);
        }
    }

    /**
     * 3.加字
     */
    private function addString()
    {
        $lens = strlen($this->str);     //计算验证码的长度
        $sessStr = '';                  //最终塞入session的验证码
        for ($i = 0; $i < $this->len; $i++) {
            //1.设置字体颜色
            $str = $this->str[mt_rand(0, $lens)];   //随机取出一个字符
            $sessStr .= $str;                       //连接验证码
            $color = $this->createColor(mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200)); //生成颜色
            //2.加字,imagettftext可控制字体,大小,颜色,旋转角度,摆放位置
            imagettftext($this->im, mt_rand(15, 25), mt_rand(-70, 70), $this->width * $i + mt_rand(5, 15),
                mt_rand(20, 40), $color, 'consola.ttf', $str);
        }
        $_SESSION['code'] = $sessStr;   //存入session中
    }

    /**
     * 2.创建画布资源
     */
    private function createPic()
    {
        $this->im = imagecreatetruecolor($this->width * $this->len, $this->height);
    }

    /**
     * 创建颜色
     * @param $r
     * @param $g
     * @param $b
     * @return int
     */
    private function createColor($r, $g, $b)
    {
        return imagecolorallocate($this->im, $r, $g, $b);
    }

    /**
     * 输出验证码图片
     */
    public function showCode()
    {
        header('content-type:image/png');
        imagepng($this->im);
        imagedestroy($this->im);
    }
}

$q = new Code();
$q->showCode();

2.HTML显示验证码

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
    <title>PHP验证码</title>
    <!--引入jquerycdn-->
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
</head>
<body>
<!--引入获取验证码图片-->
<img src="code.php" onclick="this.src='code.php?'+Math.random()">
<!--输入验证码-->
<input id="code" type="text" name="code">
<!--AJAX提交-->
<input id="checkCode" type="button" value="检查验证码">
<!--输出结果-->
<div>结果:<span style="color:red" id="result"></span></div>
</body>
<script type="text/javascript">
    $('#checkCode').click(function () {
        $.ajax({
            url: "checkCode.php",
            method: "get",
            data: {
                code: $("#code").val()      //传参
            },
            dataType: "json",
            success: function (result) {
                console.log(result)
                $('#result').text(result.msg)   //改变页面的值
            }
        })
    })
</script>
</html>

3.PHP验证验证码

<?php
class CheckCode
{
    public function __construct()
    {
        session_start();
    }

    public function check($code)
    {
        if ($code) {
            if ($code == $_SESSION['code']) {
                unset($_SESSION['code']);
                $this->jsonOutPut('验证码正确');
            } else {
                $this->jsonOutPut('验证码错误');
            }
        } else {
            $this->jsonOutPut('未输入验证码');
        }
    }
    /**
     * [输出json]
     * @param  [type] $msg [description]
     * @return [type]      [description]
     */
    public function jsonOutPut($msg)
    {
        $data = [
            'code' => 200,
            'msg' => $msg
        ];
        echo json_encode($data);
    }
}

$code = strtoupper($_GET['code'] ?? '');    //获得参数,并且全部转换为大写字母
$check = new CheckCode();
$check->check($code);                       //检查并输出

三、缩略图的制作流程

1、获取原图像大小

  • getimagesize():获取图像大小或类型
    list($width,$heifht) = getimagesize($picInfo[‘tmp_name’]);

2、计算缩略图大小

  • (1)$percent = 0.2;:计算缩放比例
    $thuWidth = $width * $percent;
    $thuHeight = $height * $percent;
  • (2)$thuWidth = 100;:定义缩略图的宽
    $thuHeight = $thuWidth * $height / $width;

3、创建画布

  • 同上验证码

4、生成缩略图

  • imagecopyresized($dst,$src,0,0,0,0,$dstWidth,$dstHeight,$srcWidth,$srcHeight);
    从原图像的原点坐标(0,0)位置开始,按照目标图像宽和高的比例进行缩放,并将其拷贝到目标图像的原点(0,0)位置
  • 参数:
    $dst:目标图像
    $src:原图像
    0,0,0,0:目标图像开始x,y坐标,原图像开始x,y坐标
    $dstWidth:目标图像的宽度
    $dstHeight:目标图像的高度
    $srcWidth:拷贝原图像的宽度
    $srcHeight:拷贝原图像的高度

5、导出 && 销毁

  • 同上验证码

6、缩略图代码展示

github :https://github.com/YY-FS/Study/tree/master/GD/Thumbnail

<?php
$file = './LFF.jpg';
list($width, $height) = getimagesize($file);
$percent = 0.3;                     //定义缩放比例
$dstWidth = $percent * $width;      //缩略图的宽
$dstHeight = $percent * $height;    //缩略图的高
$srcim = imagecreatefromjpeg($file);//从原图创建画布
$dstim = imagecreatetruecolor($dstWidth, $dstHeight);  //创建正彩色画布
imagecopyresized($dstim, $srcim, 0, 0, 0, 0, $dstWidth, $dstHeight, $width, $height);    //创建缩略图
$newFile = './LFF_thumb.jpg';       //缩略图生成地址
imagejpeg($dstim, $newFile, 100);   //导出
imagedestroy($dstim);               //销毁图片资源
imagedestroy($srcim);

四、水印的制作流程

1、添加普通水印

  • imagecopy($srcim, $waterim, 20, 20, 0, 0, $waterWidth, $waterHeight);
    表示将 $waterim 图像中坐标从 0,0 开始,宽度为$waterWidth,高度为$waterHeight 的一部分拷贝到$srcim图像中坐标为 20,20(即左上角) 的位置上

2、添加半透明水印

  • imagecopymerge($srcim, $waterim, 20, 20, 0, 0, $waterWidth, $waterHeight, 20);
    参数与imagecopy几乎完全一样,多了最后一个参数控制透明度0~100,100时则与imagecopy效果一样

3、添加文字水印

  • imagecolorallocate(画布资源,颜色R,颜色G,颜色B)
  • imagefttext ($image, $size, $angle, $x, $y, $color, $fontfile, $text[, $extrainfo = null ])
    参数:$image:画布资源
    $size:字体大小
    $angle:角度
    $x,$y:文字在目标图像的横纵坐标
    $color:字体的颜色
    $fontfile:字体样式
    $text:文字

4、水印代码展示

github :https://github.com/YY-FS/Study/tree/master/GD/WaterMark

<?php
$srcim = imagecreatefromjpeg('./LFF.jpg');
/************** 图片水印 **************/
$waterim = imagecreatefrompng('./cctv.png');
list($waterWidth, $waterHeight) = getimagesize('./cctv.png');
//普通水印
imagecopy($srcim, $waterim, 20, 20, 0, 0, $waterWidth, $waterHeight);
//半透明水印
imagecopymerge($srcim, $waterim, 20, 20, 0, 0, $waterWidth, $waterHeight, 20);
/************** 文字水印 **************/
$fontStyle = './consola.ttf';          //定义字体模式
$color = imagecolorallocate($srcim, 255, 255, 255); //RGB白色
imagefttext($srcim, 30, 0, 20, 50, $color, $fontStyle, 'YY-FS');

$file = './LFF_water.jpg';
imagejpeg($srcim, $file, 100);  //输出图像
imagedestroy($waterim);         //销毁资源
imagedestroy($srcim);

五、图片特效的制作流程

1、特效函数

  • imagefilter ($image, $filtertype[, $arg1 = null, $arg2 = null, $arg3 = null, $arg4 = null])
    过滤器 filtertype 应用到图像上,在需要时使用 arg1,arg2 和 arg3
  • filtertype参数
    IMG_FILTER_NEGATE:将图像中所有颜色反转
    IMG_FILTER_GRAYSCALE:将图像转换为灰度的
    IMG_FILTER_BRIGHTNESS:改变图像的亮度。用 arg1 设定亮度级别
    IMG_FILTER_CONTRAST:改变图像的对比度。用 arg1 设定对比度级别
    IMG_FILTER_COLORIZE:与 IMG_FILTER_GRAYSCALE 类似,不过可以指定颜色。用 arg1,arg2 和 arg3 分别指定 red,blue 和 green。每种颜色范围是 0 到 255
    IMG_FILTER_EDGEDETECT:用边缘检测来突出图像的边缘
    IMG_FILTER_EMBOSS:使图像浮雕化
    IMG_FILTER_GAUSSIAN_BLUR:用高斯算法模糊图像
    IMG_FILTER_SELECTIVE_BLUR:模糊图像
    IMG_FILTER_MEAN_REMOVAL:用平均移除法来达到轮廓效果
    IMG_FILTER_SMOOTH:使图像更柔滑。用 arg1 设定柔滑级别

2、图片特效代码展示

github :https://github.com/YY-FS/Study/tree/master/GD/Special

  • PHP后端代码
<?php
$fileInfo = $_FILES['file'];
switch ($fileInfo['type']) {            //选择合适的方法创建画布
    case 'image/jpeg':
    case 'image/jpg':
        $im = imagecreatefromjpeg($fileInfo['tmp_name']);
        break;
    case 'image/png':
        $im = imagecreatefrompng($fileInfo['tmp_name']);
        break;
    case 'image/gif':
        $im = imagecreatefromgif($fileInfo['tmp_name']);
        break;
}
switch ($_POST['filter']) {             //选择特效样式
    case 1:
        $filter = IMG_FILTER_NEGATE;    //反色
        break;
    case 2:
        $filter = IMG_FILTER_EMBOSS;    //浮雕
        break;
    case 3:
        $filter = IMG_FILTER_SELECTIVE_BLUR;    //模糊
        break;
    case 4:
        $filter = IMG_FILTER_GRAYSCALE; //灰度
        break;
}
imagefilter($im, $filter);       //图片特效绘制
$file = './filter.jpg';
imagejpeg($im, $file, 100);      //输出图像
imagedestroy($im);               //销毁图像
echo json_encode([
    'code' => 0,
    'msg' => 'success',
    'src' => $file
]);
  • HTML前端代码:注意文件的ajax传输
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图片特效</title>
    <!--引入jquerycdn-->
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <style>
        .box {
            margin: 20px auto;
            width: 400px;
        }

        #filter {
            width: 100px;
            font-size: 15px;
            height: 25px;
        }

        .img{
            width: 200px;
        }
    </style>
</head>
<body>
<div class="box">
    <div>
        <span>上传文件:</span>
        <input type="file" id="file" name="file">
    </div>
    <div style="margin: 20px 0;">
        <span>选择特效:</span>
        <select name="filter" id="filter">
            <option value="1">反色</option>
            <option value="2">浮雕</option>
            <option value="3">模糊</option>
            <option value="4">灰度</option>
        </select>
    </div>
    <button id="change">提交</button>
    <div id="img"></div>
</div>
</body>
<script type="text/javascript">
    $('#change').click(function () {
        var form = new FormData();
        form.append('file', $('#file')[0].files[0]);
        form.append('filter', $('#filter').val());
        $.ajax({
            url: "special.php",
            method: "post",
            data: form,
            processData: false, //很重要,告诉jquery不要对form进行处理
            contentType: false, //很重要,指定为false才能形成正确的Content-Type
            dataType: "json",
            success: function (result) {
                if(result.code == 0){
                    var img = '<img class="img" src="'+result.src+'">'
                    $('#img').html(img)
                }
            }
        })
    })
</script>
</html>
  • 效果展示
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值