11.GD图像处理

思考:在PHP开发中,应该会经常用到图形处理之类的,那么PHP能够处理图片吗?

引入:PHP作为一款强大的后台处理语言,操作图片是必不可少的,PHP本身不操作图片,但是可以借助强大的扩展库实现图片的操作。PHP主要使用GD库实现图片操作。

  • 验证码制作
  • 缩略图
  • 水印图

总结:PHP可以利用GD库进行各种图像操作


1. 加载GD库【掌握】

  1. GD库作为一种扩展项,需要事先加载才能使用,加载的方式就是在php.ini中开启GD扩展


    加载GD扩展.png
  1. GD库加载后,内置了很多函数供开发人员操作,可以通过操作手册索引中输入image来检索
操作手册查看GD函数.png
  1. 常用的GD函数列表
  • imagecreatetruecolor:创建一张真彩画布
  • imagecolorallocate:给画布分配颜色
  • imagefill:填充颜色
  • imagestring:水平写字符串(ASCII码)
  • imagettftext:文本写入
  • imageline:制作线段
  • imagecreatefromjpeg:打开一张jpeg图片
  • imagecreatefrompng:打开一张png图片
  • imagecopymerge:拷贝图像合并到另外一张图片资源
  • imagecopyresampled:不失真拷贝图片到另外一张图片资源
  • imagepng:保存或者输出图片,保存格式为png
  • imagejpeg:保存或者输出图片,保存格式为jpeg
  • imagedestroy:销毁资源
  • getimagesize:取得图片信息
  • pathinfo:得到文件信息

总结

  1. GD库提供了很多函数来处理图片
  2. 根据不同的需求可以使用不同的函数来完成对应的功能
  3. 列出了制作验证码、水印和缩略图所需要的常用函数

思考:验证码图片是怎么做成的呢?

引入:在开发中,几乎所有的网站都有用到验证码功能,验证码不是一个简单的字符串,通常都是将字符串放到图片上,而且加上很多干扰内容来完成。

2. 制作验证码【掌握】

定义验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写 ,是一种区分用户是计算机还是人的公共全自动程序。验证码由最初的简单字符串到现在各式各样复杂的图片、计算、问题等,只是因为计算机识别的功能已经越来越强大。

  1. 验证码制作流程
  • 制作画布:imagecreatetruecolor
  • 填充背景色:imagecolorallocate分配颜色,imagefill填充颜色
  • 写入内容:imagestring写简单内容,imagettftext写入字体文字
  • 增加干扰:imageline增加线段,imagestring增加其他符号
  • 保存图片:imagepng输出或者保存图片
  1. 简单图片制作
<?php
//制作简单图片

//1.创建画布
$img = imagecreatetruecolor(200,200);   //宽度和高度,像素单位,得到画布资源

//2.输出图片
header('content-type:image/png');
imagepng($img);                       //所有gd函数都需要图片资源

//3.销毁资源
imagedestroy($img);
  1. 简单验证码制作
<?php
    
//制作简单验证码图片
    
//1.创建画布资源
$img = imagecreatetruecolor(100,30);

//2.填充背景色
//2.1给画布分配背景颜色
$bg_color = imagecolorallocate($img,255,255,255);   #RGB三色组,纯白色

//2.2填充颜色
imagefill($img,0,0,$bg_color);                     #从0,0坐标处开始上色,自动渲染相同颜色像素点

//3.写入字符串
//3.1给要写入的字符串分配颜色
$str_color = imagecolorallocate($img,150,150,150);  #比背景颜色稍深
//3.2写入文字
imagestring($img,5,30,10,'capcha',$str_color);

//4.保存输出
//4.1保存
imagepng($img,'captcha.png');                      #保存到当前文件夹captcha.png
//4.2输出
header('content-type:image/png');
imagepng($img);

//5.销毁资源
imagedestroy($img);
  1. 封装简单验证码制作函数
<?php
//封装验证码制作函数

/*
 * 验证码制作函数
 * @param1 int $width 图片宽度
 * @param2 int $height 图片高度
 * @param3 int $lines = 10,干扰线数量,默认10条
 * @param4 int $length = 4 字符串长度,默认4个简单字符
 
*/
function getCaptcha($width,$height,$lines = 10,$length = 4){
    //1.制作画布
    $img = imagecreatetruecolor($width,$height);
    
    //2.填充背景
    $bg_c = imagecolorallocate($img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)); #随机淡色
    imagefill($img,0,0,$bg_c);
    
    //3.制作随机字符串
    $str_arr = range('A','Z');          #得到A-Z数组元素
    shuffle($str_arr);                  #打乱数组元素
    
    //定义一个字符串保留取出的所有字母
    $captcha = '';
    //循环取元素即可
    for($i = 0;$i < $length; $i++){
        //每取出一个符号就保留到$captcha
        $captcha .= $str_arr[$i];       #取乱序数组前4个元素
    }
    
    //写入图片
    $str_c = imagecolorallocate($img,mt_rand(0,100),mt_rand(0,100),mt_rand(0,100)); #随机深色
    imagestring($img,5,30,10,$captcha,$str_c);
    
    //4.制作干扰元素
    //循环制作多条
    for($i = 0;$i < $lines;$i++){
       $line_c = imagecolorallocate($img,mt_rand(120,180),mt_rand(120,180),mt_rand(120,180)); #中间颜色,每条颜色都不一样
        imageline($img,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$line_c); #随机起始位置
    }
    
    //5.输出图片
    header('content-type:image/png');
    imagepng($img);
    
    //6.销毁资源
    imagedestroy($img);
}

总结

  1. 验证码指的是印在图片上的随机字符
  2. 验证码图片的制作流程:画布->背景色->随机字符串->写入字符串->干扰->输出图片->销毁画布
  3. 验证码的功能可以很丰富,需要使用更加复杂的函数和逻辑

思考:随着版权意识越来越高,很多人已经开始给自己的图片做了版权保护处理,就是在上面增加了一些若影若现的文字或者图片,这个怎么实现呢?

引入:图片上加入内容,其实就是制作水印的一个过程。验证码也可以理解为是一个带文字水印的图片。更多的水印是通过放置一张图片到上面来实现的。

3. 制作水印图片【掌握】

定义:制作水印图片,就是往一张图片上放入一些文字或者图片元素,在不是特别影响原图的使用的前提下,又能有版权追溯(防止别人盗图商用)。

  1. 水印制作流程(图片版)
  • 打开原图:imagecreatefromjpeg/png,从jpeg(基本上都是)打开原图资源
  • 打开水印图:与原图一样,只是图片通常是png
  • 复制水印图合并到原图上:imagecopymerge
  • 保存图片:imagejpeg/png
  • 关闭资源
  1. 实现水印图(原图desktop.jpg,水印图php.png)
<?php
//制作水印图

//1.打开要添加水印图的资源
$dst = imagecreatefromjpeg('desktop.jpg');

//2.打开水印图片资源
$src = imagecreatefrompng('php.png');

//3.采样复制合并:全部水印图放到原图左上角
$src_info = getimagesize('php.jpg'); #获取图片信息返回数组,0元素为宽,1元素为高
imagecopymerge($dst,$src,0,0,0,0,$src_info[0],$src_info[1],50); #透明度50

//4.保存图片
header('content-type:image/jpeg');
imagejpeg($dst);
imagejpeg($dst,'water.jpg');

//5.销毁资源
imagedestroy($dst);
imagedestroy($src);
  1. 封装水印图制作函数
<?php
    
//封装水印图制作函数
/*
 * 制作水印图
 * @param1 string $image,要添加水印的图片地址
 * @param2 string $path,水印图制作完成后存储路径
 * @param3 string $water,水印图图片地址
 * @param4 int $pct = 50,透明度,默认50
 * @return string 新生成图片的名字
*/
function getWatermark($image,$path,$water,$pct = 50){
    //1.打开原图资源
    $dst = imagecreatefromjpeg($image);
    
    //2.打开水印图资源
    $src = imagecreatefrompng($water);
    
    //3.采样复制合并:存放到做上角(不需要计算)
    $src_info = getimagesize($water);       
    imagecopymerge($dst,$src,0,0,0,0,$src_info[0],$src_info[1],$pct);
    
    //4.保存图片
    //获取原图片路径和名字信息
    $image_info = pathinfo($image); #返回数组:extension是后缀名,filename是纯名字
    //拼凑新文件名字
    $water_name = $image_info['filename'] . '_water' . '.' . $image_info['extension'];
    imagejpeg($dst,$path . '/' . $water_name);
    
    //5.销毁资源
    imagedestroy($dst);
    imagedestroy($src);
    
    //6.返回文件名
    return $water_name;
}

总结

  1. 水印图分为文字水印图(验证码)和图片水印图
  2. 水印图的制作流程:打开原图->打开水印图->采样复制合并->保存图片->销毁资源
  3. 水印图不像验证码,一般是规定位置规定水印图样章的

思考:在很多网站上,上传图片的时候都会有个小图可以看的,那么是怎么实现的呢?

引入:其实小图的本质并不是用户上传的,而是系统根据系统需求在用户上传原图的时候,制作的一个小图。这个小图就是缩略图。

4. 制作缩略图【掌握】

定义:制作缩略图,就是将原图放到一个固定的大小的图片资源里,形成一张新的图片。通常是把大图做成小图,因此叫做缩略图。

  1. 缩略图制作原理
  • 打开原图资源:imagecreatefromjpeg
  • 创建缩略图资源:imagecreatetruecolor
  • 采样复制合并:imagecopyresampled(不失真)
  • 保存缩略图资源:imagejpeg(较多)
  • 销毁资源
  1. 实现缩略图
<?php
    
//制作缩略图
//1.打开原图资源
$src = imagecreatefromjpeg('desktop.jpg');

//2.创建缩略图资源
$dst = imagecreatetruecolor(100,100);

//3.采样复制合并
$src_info = getimagesize('desktop.jpg');
imagecopyresampled($dst,$src,0,0,0,0,100,100,$src_info[0],$src_info[1]);

//4.保存输出
header('content-type:image/jpeg');
imagejpeg($dst);
imagejpeg($dst,'desktop_thumb.jpg');

//5.销毁资源
imagedestroy($src);
imagedestroy($dst);
  1. 缩略图注意事项:原图与缩略图比例不一样采用全部填充满,会导致缩略图“变形”,这种时候的解决方案如下
  • 求出原图的宽高比
  • 求出缩略图的宽高比
  • 比较原图的宽高比和缩略图的宽高比
    • 原图宽高比大于缩略图宽高比,说明原图太宽,应该让缩略图的宽占满,高按比例求出来
    • 原图宽高比小于缩略图宽高比,说明原图太高,应该让缩略图的高占满,宽按比例求出来
  • 不管哪种情况,势必会有缩略图部分区域没有放上内容,这个时候缩略图背景填充为白色(补白)
  • 根据计算出来的实际宽高像素,将图片居中到缩略图中
  1. 制作缩略图函数(补白)
<?php
    
//制作补白效果缩略图

/*
 @param1 string $image,原图地址
 @param2 string $path,缩略图存储路径
 @param3 int $width = 100,缩略图宽
 @param4 int $height = 100,缩略图高
*/
function getThumb($image,$path,$width = 100,$height = 100){
    //1.打开原图资源
    $src = imagecreatefromjpeg($image);
    
    //2.创建缩略图画布
    $thu = imagecreatetruecolor($width,$height);
    
    //3.补白:背景填充白色
    $white = imagecolorallocate($thu,255,255,255);
    imagefill($thu,0,0,$white);
    
    //4.计算缩略图所放图片的实际宽和高:通过原图宽高比和缩略图宽高比来比较
    $src_info = getimagesize($image);
    
    //原图宽高比
    $src_c = $src_info[0] / $src_info[1];
    $thu_c = $width / $height;
    
    //判定
    if($src_c > $thu_c){
        #原图宽高比大于缩略图,说明原图很宽,那么缩略图中宽度应该占满
        $thu_w = $width;    #占满缩略图宽
        $thu_h = ceil($thu_w / $src_c); #取整
    }else{
        #原图宽高比小于缩略图,说明原图很高,那么缩略图中高度应该占满
        $thu_h = $height;
        $thu_w = ceil($thu * $src_c);
    }
    
    //5.采样复制粘贴:还需让缩略图居中
    $x = ceil(abs($thu_w - $width) / 2);    //绝对值除以2取整
    $y = ceil(abs($thu_h - $height) / 2);
    imagecopyresampled($thu,$src,$x,$y,0,0,$thu_w,$thu_h,$src_info[0],$src_info[1]);
    
    //6.保存图片
    $image_info = pathinfo($image);
    //构造新文件名字
    $newname = $image_info['filename'] . '_thumb' . '.' . $image_info['extension'];
    
    imagejpeg($thu,$path . '/' . $newname);
    
    //7.销毁资源
    imagedestroy($src);
    imagedestroy($thu);
    
    //8.返回结果
    return $newname;
}

总结

  1. 缩略图是在用户上传原图的时候系统根据需求自动生成的
  2. 缩略图要保证与原图比例一致,就需要进行缩略图中图片实际的尺寸,并进行补白
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • PHP中GD库的使用 GD简介 PHP 不仅限于只产生 HTML 的输出,还可以创建及操作多种不同格式的图像文件。...
    dptms阅读 1,006评论 0 2
  • 夕阳加快了步伐 希望生一场清风 奔跑在刚到的闷热的五月里 那如清水的弯月 也涤不去我一天滴淌的辛劳 我前面的身影 ...
    向史而新阅读 163评论 0 5
  • 看看言情小说,看看偶像剧,日常沉迷于虚假的男主腹黑或温暖中,幻想自己是那个万千宠爱集一身的女主。应该是小女生的通病...
    瑾_jessica阅读 206评论 0 0
  • 这一周过得中规中矩! 端午回来,节前上报的牛奶没及时拿,我得抓紧。周二...
    fef73b8af426阅读 160评论 0 0
  • 接到老师的电话,说要来家访,激动又兴奋,约定好了时间,去奶奶家接儿子、将家里打扫的一尘不染,为此午饭都没...
    泥道至简阅读 163评论 0 0