header("content-type:text/html;charset=utf-8");
/**
* GD库提供图像处理功能
* GD库的配置
* 1.配置php.ini,开启extension=gd2/php_gd2.dll,两种书写风格都可识别
* 2.开启extension_dir="ext",这一步是指定扩展目录
* 3.重启服务器
*
* 检测GD扩展是否已开启
* 1.phpinfo();
* 2.extension_loaded('gd')
* 3.function_exists('gd_info')
* 4.gd_info()
* 5.get_defined_functions()
*/
//检测扩展是否已开启
var_dump(extension_loaded('gd'));//bool(true)
//检测函数是否可以使用
var_dump(function_exists('gd_info'));//bool(true)
//得到gd库信息
var_dump(gd_info());
//得到所有已定义的函数,在其中找gd相关函数
print_r(get_defined_functions());
//1.创建画布:imagecreatetruecolor($width, $height)
$image = imagecreatetruecolor(500, 300);
//2.创建颜色:imagecolorallocate($image, $red, $green, $blue)
$red = imagecolorallocate($image, 255, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 255);
//3.绘画:imagechar()水平绘制一个字符;imagecharup()垂直绘制一个字符;imagestring()水平绘制字符串
//imagechar($image, $font, $x, $y, $char, $color),其他函数同理
imagechar($image, 5, 30, 50, 'H', $red);
imagestring($image, 18, 100, 120, 'still', $blue);//18不生效,字号最大到5
//4.输出
//4.1告诉浏览器以图片的形式显示:加一个header(),image/jpeg、image/gif、image/png
header("content-type:image/png");
//4.2输出图像:imagejpeg($image);或imagepng()、imagegif()
imagepng($image);//输出到浏览器
imagepng($image, 'images/demo.png');//保存文件
//5.销毁图像
imagedestroy($image);
/**
* 1.画布默认黑色,修改为白色
* 2.字体自定义
*/
//创建随机颜色
$randColor = imagecolorallocate($image, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
//imagefilledrectangle()绘制填充矩形
imagefilledrectangle($image, 0, 0, 500, 500, $white);
//imagettftext($image,$size,$angle,$x,$y,$color, $fontfile, $text)用TrueType字体向图像写入文本
//$x和$y定义字符的左下角,$y是基线位置
//在测试中发现fontfile写绝对路径才会生效
imagettftext($image, 28, 30, 50, 280, $randColor, 'C:\study\gd\fonts\consola.ttf', 'This is a show');
imagettftext($image, 22, 0, 300, 120, $randColor, 'C:\website-study\gd\PALSCRI.TTF', 'HanyStill');
/**
* range(0,9)生成包含0-9的数组
* array_rand(array, num)从数组中取出多个随机单元的key值
* implode([glue],array) [用glue]将一维数组的值连接为字符串,别名join
* array_merge(array...)合并一个或多个数组
* array_flip(array) 交换数组中的key和value
* explode(delimiter,string) 用delimiter分割string,返回数组
*/
switch ($type) { //type取值 1.数字 2.字母 3.数字+字母 4.汉字
case 1:
$code = implode(array_rand(range(0, 9), $length));
break;
case 2:
$arr = array_flip(array_merge(range('a', 'z'), range('A', 'Z'));//键值为a-Z的数组
$code = implode(array_rand($arr, $length));
break;
case 3:
$arr = array_flip(array_merge(range(0, 9), range('a', 'z'), range('A', 'Z'));
$code = implode(array_rand($arr, $length));
break;
case 4:
$str = "在,中,国,共,产,党,的,领,导,下,人,民,生,活,会,更,加,美,好,因,为,力,量,拧,成,一,股,绳,
困,难,和,险,阻,也,击,垮,不,了,我,们,最,后,衷,心,祝,愿,祖,国,繁,荣,昌,盛";
$code = implode(array_rand(array_flip(explode(',', $str)), $length));
break;
default:
//exit()输出一个消息并退出当前脚本
exit('非法参数');
break;
}
//imagefontwidth(size)|imagefontheight(size) 得到字体的宽高(字体最大为28),用于计算$x,$y
$textwidth = imagefontwidth(28);//9
$textheight = imagefontheight(28);//15
for($i=0; $i<$length; $i++){//$length 验证码长度
$size = mt_rand(20,28);
$angle = mt_rand(-15, 15);
$x = 15+45*$i+mt_rand(0,36);//计算得到宽度范围
$y = $textheight/1.5;
//mb_substr($string, $start, $length, $encoding) 获取多字节字符串的部分
$text = mb_substr($string, $i, 1, 'utf-8');
imagettftext($image, $size, $angle, $x, $y, getRandColor($image), $fontFile, $text);
}
//添加像素当作干扰元素:imagesetpixel($image, $x, $y, $color)
for($i=0; $i<50; $i++){
imagesetpixel($image, mt_rand(0,$width), mt_rand(0,$height), getRandColor($image));
}
//绘制线段当作干扰元素:imageline($image, $x1, $y1, $x2, $y2, $color)
for($i=0; $i<3; $i++){
imageline($image, mt_rand(0,$width), mt_rand(0,$height),
mt_rand(0,$width), mt_rand(0,$height), getRandColor($image));
}
//绘制椭圆弧:imagearc($image, $cx, $cy, $width, $height, $start, $end, $color)
//$cx/$cy是原点,$width/$height是椭圆的宽高,$start/$end是起始角度和结束角度
for($i=0; $i<3; $i++){
imagearc($image, mt_rand(0,$width), mt_rand(0,$height),
mt_rand(0, $width/2), mt_rand(0, $height/2),
mt_rand(0,360), mt_rand(0, 360), getRandColor($image));
}
Class Captcha{
private $_fontfile = '';
private $_size = 20;
private $_width = 300;
private $_height = 50;
private $_length = 6;
private $_image = null;
private $_snow = 0;//雪花数量
private $_pixel = 0;//像素数量
private $_line = 0;//线段数量
/**
* 初始化数据
*/
public function __construct($config=array()){
if(is_array($config) && count($config)>0){
//检测文件是否存在并且可读
if(isset($config['fontfile']) && is_file($config['fontfile']) && is_readable($config['fontfile'])){
$this->_fontfile = $config['fontfile'];
}else{
return false;
}
//检测是否设置字体大小
if(isset($config['size']) && $config['size']>0){
$this->_size = $config['size'];
}
//检测是否设置画布的宽和高
if(isset($config['width']) && $config['width']>0){
$this->_width = $config['width'];
}
if(isset($config['height']) && $config['height']>0){
$this->_height = $config['height'];
}
//检测是否设置验证码的长度
if(isset($config['length']) && $config['length']>0){
$this->_length = $config['length'];
}
//检测是否设置干扰元素
if(isset($config['snow']) && $config['snow']>0){
$this->_snow = (int)$config['snow'];
}
if(isset($config['pixel']) && $config['pixel']>0){
$this->_pixel = (int)$config['pixel'];
}
if(isset($config['line']) && $config['line']>0){
$this->_line = (int)$config['line'];
}
//创建画布资源
$this->_image = imagecreatetruecolor($this->_width, $this->_height);
return $this->_image;
}else{
return false;
}
}
/**
* 得到验证码
*/
public function getCaptcha(){
//填充矩形
$white = imagecolorallocate($this->_image, 255, 255, 255);
imagefilledrectangle($this->_image, 0, 0, $this->_width, $this->_height, $white);
//生成验证码
$code = $this->_generateStr($this->_length);
if(false===$code){
return false;
}
//绘制验证码
for($i=0; $i<$this->_length; $i++){
$angle = rand(-15, 15);
$x = ceil($this->_width/$this->_length * $i);
$y = ceil($this->_height/1.5);//ceil(num)向上取整
//$text = mb_substr($code, $i, 1, 'utf-8');//针对中文截取
$text = $code[$i];
imagettftext($this->_image, $this->_size, $angle, $x, $y, $this->_getRandColor(), $this->_fontfile, $text);
}
//绘制干扰元素
if($this->_snow){
$this->_getSnow();
}else{
if($this->_pixel){
$this->_getPixel();
}
if($this->_line){
$this->_getLine();
}
}
//输出
header('content-type:image/png');
imagepng($this->_image);
imagedestroy($this->_image);
return strtolower($code);
}
/**
* 产生验证码字符
* @param int $length 验证码字符长度
*/
private function _generateStr($length = 4){
if($length<1 || $length>10){
return false;
}
$chars = array(
'a','b','c','d','e','f','g','h','j','k','m','n','p','q','r','s','t','y',
'A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','T','Y',
1,2,3,4,5,6,7,8,9
);
$str = implode(array_rand(array_flip($chars), $length));
return $str;
}
/**
* 产生随机颜色
*/
private function _getRandColor(){
return imagecolorallocate($this->_image, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255));
}
/**
* 产生雪花
*/
private function _getSnow(){
for($i=0; $i<$this->_snow; $i++){
imagestring($this->_image, mt_rand(1,5), mt_rand(0,$this->_width), mt_rand(0, $this->_height),
'*', $this->_getRandColor());
}
}
/**
* 产生像素
*/
private function _getPixel(){
for($i=0; $i<$this->_pixel; $i++){
imagesetpixel($this->_image, mt_rand(0,$this->_width), mt_rand(0,$this->_height), $this->_getRandColor());
}
}
/**
* 产生线段
*/
private function _getLine(){
for($i=0; $i<$this->_line; $i++){
imageline($this->_image, mt_rand(0,$this->_width), mt_rand(0,$this->_height),
mt_rand(0,$this->_width), mt_rand(0,$this->_height), $this->_getRandColor());
}
}
}
$filename = 'images\code.png';
//getimagesize(filename)得到图片大小,会识别是否是真正的图片,如果是则返回数组,不是返回false
//返回值是一个数组 {[0]=>width [1]=>height [2]=>mark [3]=>string [mime]=>mime}
//[2]mark为图像类型标记 1=GIF 2=JPG 3=PNG
//[3]string为文本字符串,内容为 height="yyy" width="xxx"
//[mime]为字符串,内容为 image/png | image/jpeg | image/gif 等
$imageInfo = getimagesize($filename);
//list(var)把数组中的值赋给一些变量
list($src_width, $src_height) = $imageInfo;
//创建一个100x100的缩略图
$dst_width = 100;
$dst_height = 100;
//创建目标画布资源
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
//通过图片文件创建原画布资源
//imagecreatefrompng()|imagecreatefromjpeg()|imagecreatefromgif()
$src_image = imagecreatefrompng($filename);
$dst_x = 0;
$dst_y = 0;//目标起始坐标点
$src_x = 0;
$src_y = 0;//源起始坐标点
//imagecopyresampled()拷贝图像并调整大小
imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_width, $dst_height, $src_width, $src_height);
//以png格式将图像输出到文件
imagepng($dst_image, 'images/thumb_100x100.jpg');
imagedestroy($src_image);
imagedestroy($dst_image);
1.获取文件操作优化
/**
* 获取图像文件信息,包括宽高/创建函数/输出函数/扩展名
*/
function getImageInfo($filename){
if(!$info = getimagesize($filename)){
exit('文件不是真实图片');
}
$fileInfo['width'] = $info[0];
$fileInfo['height'] = $info[1];
//image_type_to_mime_type() 根据图像类型返回mime类型
$mime = image_type_to_mime_type($info[2]);//比如$mime='image/jpeg'
$createFun = str_replace('/','createfrom', $mime);
$outFun = str_replace('/', '', $mime);
$fileInfo['createFun'] = $createFun;
$fileInfo['outFun'] = $outFun;
//image_type_to_extension(type,dot)取得图像类型的文件后缀,dot指是否在后缀前加点,默认为true
$ext = image_type_to_extension($info[2]);//比如$ext='.jpg'
$fileInfo['ext'] = strtolower($ext);
return $fileInfo;
}
2.形成缩略图操作优化
/**
* @description: 形成缩略图的函数
* @param $file 图像文件
* @param $dest 缩略图的保存路径
* @param $pre 缩略图文件名前缀
* @param $delSource 是否删除源文件
* @param $scale 缩放比例
* @param $dst_width 最大宽度
* @param $dst_height 最大高度
* @return 最终保存路径和文件名
*/
function thumb($file, $dest='thumb', $pre='thumb_', $delSource=false, $scale=0.5, $dst_width=null, $dst_height=null){
$fileInfo = getImageInfo($file);
$src_width = $fileInfo['width'];
$src_height = $fileInfo['height'];
//如果指定最大宽高,则等比例缩放
//is_numeric(var)检测变量是否为数字或数字字符串
if (is_numeric($dst_width) && is_numeric($dst_height)) {
//宽高等比缩放算法
$ratio = $src_width / $src_height;
if ($dst_width / $dst_height > $ratio) {
$dst_width = $dst_width * $ratio;
} else {
$dst_height = $dst_width / $ratio;
}
} else { //不指定最大宽高按照默认比例缩放
$dst_width = ceil($src_width * $scale);
$dst_height = ceil($src_height * $scale);
}
$src_image = $fileInfo['createFun']($file);
$dst_image = imagecreatetruecolor($dst_width, $dst_height);
imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
//检测目标目录是否存在,不存在则创建
if ($dest && !file_exists($dest)) {
//mkdir(pathname[,mode,recursive])新建一个由pathname指定的目录
//mode指定访问权限,默认0777,意为最大可能的访问权限,在windows下不生效
//recursive adj.递归的 是否允许创建嵌套目录,默认false
mkdir($dest);
}
$randNum = mt_rand(100000, 999999);
$dstName = "{$pre}{$randNum}" . $fileInfo['ext']; //图片名称 例如thumb_121212.jpg
$destination = $dest ? $dest . '/' . $dstName : $dstName; //保存路径 destination n.目标,目的地
$fileInfo['outFun']($dst_image, $destination);
if($delSource){
//unlink(file)删除文件
unlink($file);
}
imagedestroy($dst_image);
imagedestroy($src_image);
return $destination;
}
/**
* @description: 给指定图片添加文字水印
* @param $filename 图像文件
* @param $fontfile 水印字体文件
* @param $text 水印内容
* @param $dest 水印图片保存位置
* @param $pre 水印图文件名前缀
* @param $delSource 是否删除源文件
* @param $red 水印颜色红色分量
* @param $green 水印颜色绿色分量
* @param $blue 水印颜色蓝色分量
* @param $alpha 水印透明度
* @param $size 字体大小
* @param $angle 字体倾斜角度
* @param $x 水印位置x坐标,x和y定义了字符的左下角
* @param $y 水印位置y坐标
* @return 水印图保存路径和名称
*/
function getWaterText($filename, $fontfile, $text='watermark', $dest='watermark', $pre='waterText_', $delSource=false,
$red=255, $green=0, $blue=0, $alpha=100, $size=30, $angle=0, $x=0, $y=30){
$fileInfo = getImageInfo($filename);
$image = $fileInfo['createFun']($filename);
//imagecolorallocatealpha($image, red, green, blue, $alpha) 为一幅图像分配颜色和透明度
//alpha取值范围(0,127),0表示完全不透明,127表示完全透明
$color = imagecolorallocatealpha($image, $red, $green, $blue, $alpha);
imagettftext($image, $size, $angle, $x, $y, $color, $fontfile, $text);
if($dest && !file_exists($dest)){
mkdir($dest);
}
$randNum = mt_rand(100000, 999999);
$dstName = "{$pre}{$randNum}".$fileInfo['ext'];
$destination = $dest ? $dest.'/'.$dstName : $dstName;
$fileInfo['outFun']($image, $destination);
if($delSource){
unlink($filename);
}
imagedestroy($image);
return $destination;
}
/**
* @description: 给指定图像添加图片水印
* @param $dstFile 要添加水印的图片文件
* @param $srcFile 水印文件
* @param $position 水印位置
* @param $pct 水印和图片的融合程度
* @param $pre 水印图的文件名前缀
* @param $dest 水印图的保存路径
* @param $delSource 是否删除源文件
* @return 水印图的保存路径和文件名
*/
function getWaterPic($dstFile, $srcFile, $position=0, $pct=50, $pre='waterPic_', $dest='watermark', $delSource=false){
$dstInfo = getImageInfo($dstFile);
$srcInfo = getImageInfo($srcFile);
$dst_image = $dstInfo['createFun']($dstFile);
$src_image = $srcInfo['createFun']($srcFile);
$dst_width = $dstInfo['width'];
$dst_height = $dstInfo['height'];
$src_width = $srcInfo['width'];
$src_height = $srcInfo['height'];
switch ($position) {
case 0://左上
$x = 0;
$y = 0;
break;
case 1://中上
$x = ($dst_width - $src_width)/2;
$y = 0;
break;
case 2://右上
$x = $dst_width - $src_width;
$y = 0;
break;
case 3://左中
$x = 0;
$y = ($dst_height - $src_height)/2;
break;
case 4://居中
$x = ($dst_width - $src_width)/2;
$y = ($dst_height - $src_height)/2;
break;
case 5://右中
$x = $dst_width - $src_width;
$y = ($dst_height - $src_height)/2;
break;
case 6://左下
$x = 0;
$y = $dst_height - $src_height;
break;
case 7://中下
$x = ($dst_width - $src_width)/2;
$y = $dst_height - $src_height;
break;
case 8://右下
$x = $dst_width - $src_width;
$y = $dst_height - $src_height;
break;
default:
$x = 0;
$y = 0;
break;
}
//imagecopymerge($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $src_width, $src_height, $pct);
//拷贝并合并图像的一部分 pct决定合并程度,范围(0,100),100表示完全不融合,0表示完全融合,源图透明
imagecopymerge($dst_image, $src_image, $x, $y, 0, 0, $src_width, $src_height, $pct);
if($dest && !file_exists($dest)){}
$randNum = mt_rand(100000, 999999);
$dstName = "{$pre}{$randNum}".$dstInfo['ext'];
$destination = $dest ? $dest.'/'.$dstName : $dstName;
$dstInfo['outFun']($dst_image, $destination);
if($delSource){
unlink($dstFile);
}
imagedestroy($dst_image);
imagedestroy($src_image);
return $destination;
}