文档章节

仿百度GIF验证码 GIFEncoder 跳动验证码 随机背景色、颜色、字体、子大小、偏移、干扰线等

letwang
 letwang
发布于 2013/12/30 13:22
字数 990
阅读 608
收藏 7
点赞 1
评论 2
<?php
session_start ();

$SEESIN ['captcha'] = mt_rand ( 1111, 9999 );//py by:http://my.oschina.net/cart/

$imagedata = generateGif ( $SEESIN ['captcha'] );
$delay = array(20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20);//每帧动画延迟的时间

$gif = new GIFEncoder ( $imagedata,  $delay);
header ( 'Content-type:image/gif' );
// var_dump($SEESIN);
echo $gif->GetAnimation ();

function generateGif($str, $length = 4, $width = 60, $height = 22) {
	$width = ($length * 10 + 10) > $width ? $length * 10 + 10 : $width;
	// 生成一个32帧的GIF动画
	for($i = 0; $i < 32; $i ++) {
		ob_start ();
		$image = imagecreatetruecolor ( $width, $height );
		// 背景色
		imagefill ( $image, 0, 0, imagecolorallocate ( $image, 255, 255, 255 ) );
		// 设定文字随机颜色
		$colorList = array (
				imagecolorallocate ( $image, 15, 73, 210 ),
				imagecolorallocate ( $image, 0, 64, 0 ) 
		);
		//设定文字随机字体
		$fontList = array(
				'public/font/msyhbd.ttf',
				'public/font/simsun.ttc',
				'public/font/arial.ttf'
		);
		if ($i > 0) { // 屏蔽第一帧
			$left = 10;
			$top = 15;
			for($k = 0; $k < $length; $k ++) {
				imagettftext ( $image, 12, mt_rand (0, 10), ($left * $k) + mt_rand ( 0, 15 ), $top + mt_rand ( 0, 10 ), $colorList[array_rand($colorList)], $fontList[array_rand($fontList)], mb_substr ( $str, $k, 1 ) );
			}
		}
		// 添加点点
		for($k = 0; $k < 20; $k ++) {
			imagesetpixel ( $image, mt_rand () % 50, mt_rand () % 40, $colorList[array_rand($colorList)] );
		}
		// 添加干扰线
		for($k = 0; $k < 3; $k ++) {
			if (mt_rand ( 0, 1 )) {
				// 直线
				imageline ( $image, mt_rand ( 0, $width ), mt_rand ( 0, $height ), mt_rand ( 0, $width ), mt_rand ( 0, $height ), $colorList[array_rand($colorList)] );
			} else {
				// 弧线
				$w = mt_rand ( 0, $width );
				$h = mt_rand ( 0, $height );
				imagearc ( $image, $width - floor ( $w / 2 ), floor ( $h / 2), $w, $h, mt_rand ( 90, 180 ), mt_rand ( 180, 270 ), $colorList[array_rand($colorList)] );
			}
		}
		imagegif ( $image );
		imagedestroy ( $image );
		$imagedata [] = ob_get_contents ();
		ob_clean ();
		++ $i;
	}
	return $imagedata;
}

class GIFEncoder {
	var $GIF = "GIF89a"; /* GIF header 6 bytes */
	var $VER = "GIFEncoder V2.06"; /* Encoder version */
	var $BUF = Array ();
	var $LOP = 0;
	var $DIS = 2;
	var $COL = - 1;
	var $IMG = - 1;
	var $ERR = Array (
			'ERR00' => "Does not supported function for only one image!",
			'ERR01' => "Source is not a GIF image!",
			'ERR02' => "Unintelligible flag ",
			'ERR03' => "Could not make animation from animated GIF source" 
	);
	function GIFEncoder($GIF_src, $GIF_dly = 100, $GIF_lop = 0, $GIF_dis = 0, $GIF_red = 0, $GIF_grn = 0, $GIF_blu = 0, $GIF_mod = 'bin') {
		if (! is_array ( $GIF_src ) && ! is_array ( $GIF_tim )) {
			printf ( "%s: %s", $this->VER, $this->ERR ['ERR00'] );
			exit ( 0 );
		}
		$this->LOP = ($GIF_lop > - 1) ? $GIF_lop : 0;
		$this->DIS = ($GIF_dis > - 1) ? (($GIF_dis < 3) ? $GIF_dis : 3) : 2;
		$this->COL = ($GIF_red > - 1 && $GIF_grn > - 1 && $GIF_blu > - 1) ? ($GIF_red | ($GIF_grn << 8) | ($GIF_blu << 16)) : - 1;
		
		for($i = 0, $src_count = count ( $GIF_src ); $i < $src_count; $i ++) {
			if (strToLower ( $GIF_mod ) == "url") {
				$this->BUF [] = fread ( fopen ( $GIF_src [$i], "rb" ), filesize ( $GIF_src [$i] ) );
			} elseif (strToLower ( $GIF_mod ) == "bin") {
				$this->BUF [] = $GIF_src [$i];
			} else {
				printf ( "%s: %s ( %s )!", $this->VER, $this->ERR ['ERR02'], $GIF_mod );
				exit ( 0 );
			}
			if (substr ( $this->BUF [$i], 0, 6 ) != "GIF87a" && substr ( $this->BUF [$i], 0, 6 ) != "GIF89a") {
				printf ( "%s: %d %s", $this->VER, $i, $this->ERR ['ERR01'] );
				exit ( 0 );
			}
			for($j = (13 + 3 * (2 << (ord ( $this->BUF [$i] {10} ) & 0x07))), $k = TRUE; $k; $j ++) {
				switch ($this->BUF [$i] {$j}) {
					case "!" :
						if ((substr ( $this->BUF [$i], ($j + 3), 8 )) == "NETSCAPE") {
							printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR ['ERR03'], ($i + 1) );
							exit ( 0 );
						}
						break;
					case ";" :
						$k = FALSE;
						break;
				}
			}
		}
		GIFEncoder::GIFAddHeader ();
		for($i = 0, $count_buf = count ( $this->BUF ); $i < $count_buf; $i ++) {
			GIFEncoder::GIFAddFrames ( $i, $GIF_dly [$i] );
		}
		GIFEncoder::GIFAddFooter ();
	}
	function GIFAddHeader() {
		$cmap = 0;
		
		if (ord ( $this->BUF [0] {10} ) & 0x80) {
			$cmap = 3 * (2 << (ord ( $this->BUF [0] {10} ) & 0x07));
			
			$this->GIF .= substr ( $this->BUF [0], 6, 7 );
			$this->GIF .= substr ( $this->BUF [0], 13, $cmap );
			$this->GIF .= "!\377\13NETSCAPE2.0\3\1" . GIFEncoder::GIFWord ( $this->LOP ) . "\0";
		}
	}
	function GIFAddFrames($i, $d) {
		$Locals_str = 13 + 3 * (2 << (ord ( $this->BUF [$i] {10} ) & 0x07));
		
		$Locals_end = strlen ( $this->BUF [$i] ) - $Locals_str - 1;
		$Locals_tmp = substr ( $this->BUF [$i], $Locals_str, $Locals_end );
		
		$Global_len = 2 << (ord ( $this->BUF [0] {10} ) & 0x07);
		$Locals_len = 2 << (ord ( $this->BUF [$i] {10} ) & 0x07);
		
		$Global_rgb = substr ( $this->BUF [0], 13, 3 * (2 << (ord ( $this->BUF [0] {10} ) & 0x07)) );
		$Locals_rgb = substr ( $this->BUF [$i], 13, 3 * (2 << (ord ( $this->BUF [$i] {10} ) & 0x07)) );
		
		$Locals_ext = "!\xF9\x04" . chr ( ($this->DIS << 2) + 0 ) . chr ( ($d >> 0) & 0xFF ) . chr ( ($d >> 8) & 0xFF ) . "\x0\x0";
		
		if ($this->COL > - 1 && ord ( $this->BUF [$i] {10} ) & 0x80) {
			for($j = 0; $j < (2 << (ord ( $this->BUF [$i] {10} ) & 0x07)); $j ++) {
				if (ord ( $Locals_rgb {3 * $j + 0} ) == ($this->COL >> 0) & 0xFF && ord ( $Locals_rgb {3 * $j + 1} ) == ($this->COL >> 8) & 0xFF && ord ( $Locals_rgb {3 * $j + 2} ) == ($this->COL >> 16) & 0xFF) {
					$Locals_ext = "!\xF9\x04" . chr ( ($this->DIS << 2) + 1 ) . chr ( ($d >> 0) & 0xFF ) . chr ( ($d >> 8) & 0xFF ) . chr ( $j ) . "\x0";
					break;
				}
			}
		}
		switch ($Locals_tmp {0}) {
			case "!" :
				$Locals_img = substr ( $Locals_tmp, 8, 10 );
				$Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 );
				break;
			case "," :
				$Locals_img = substr ( $Locals_tmp, 0, 10 );
				$Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 );
				break;
		}
		if (ord ( $this->BUF [$i] {10} ) & 0x80 && $this->IMG > - 1) {
			if ($Global_len == $Locals_len) {
				if (GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len )) {
					$this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
				} else {
					$byte = ord ( $Locals_img {9} );
					$byte |= 0x80;
					$byte &= 0xF8;
					$byte |= (ord ( $this->BUF [0] {10} ) & 0x07);
					$Locals_img {9} = chr ( $byte );
					$this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
				}
			} else {
				$byte = ord ( $Locals_img {9} );
				$byte |= 0x80;
				$byte &= 0xF8;
				$byte |= (ord ( $this->BUF [$i] {10} ) & 0x07);
				$Locals_img {9} = chr ( $byte );
				$this->GIF .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp);
			}
		} else {
			$this->GIF .= ($Locals_ext . $Locals_img . $Locals_tmp);
		}
		$this->IMG = 1;
	}
	function GIFAddFooter() {
		$this->GIF .= ";";
	}
	function GIFBlockCompare($GlobalBlock, $LocalBlock, $Len) {
		for($i = 0; $i < $Len; $i ++) {
			if ($GlobalBlock {3 * $i + 0} != $LocalBlock {3 * $i + 0} || $GlobalBlock {3 * $i + 1} != $LocalBlock {3 * $i + 1} || $GlobalBlock {3 * $i + 2} != $LocalBlock {3 * $i + 2}) {
				return (0);
			}
		}
		return (1);
	}
	function GIFWord($int) {
		return (chr ( $int & 0xFF ) . chr ( ($int >> 8) & 0xFF ));
	}
	function GetAnimation() {
		return ($this->GIF);
	}
}




© 著作权归作者所有

共有 人打赏支持
letwang
粉丝 139
博文 67
码字总数 76298
作品 0
南京
技术主管
加载中

评论(2)

letwang
letwang

引用来自“kuaiyan312”的评论

写的很不错,收藏学习了。这里说明下,不知道是作者是不打算用session还是手误。超全局的$_SESSION这个地方,没有明白啊!哈哈

$SEESIN ['captcha'] 没有看到么?
哈哈 或者$SEESIN 我只是害羞的赋值了一下,抛砖引玉啊
kuaiyan312
kuaiyan312
写的很不错,收藏学习了。这里说明下,不知道是作者是不打算用session还是手误。超全局的$_SESSION这个地方,没有明白啊!哈哈
网上几种常见校验码图片分析

前几天受刺激了,准备把CSDN的校验码图片修改。就上网找了一些参考示例。和分析了一些校验码的功能。不敢独享,整理到一起,跟大家分享。 至于CSDN新的校验码写法,不是这里面的任何一种。也...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

PHP生成验证码--Micoolcoder

多功能自定义PHP生成验证码 新增伪静态案例 支持自定义参数说明: 第一个参数 CS:简体中文 CT:繁体中文 E:大小英文 e:小写英文 D:数字 Ee:大小写英文 EeD:大小英文数字 ED:大写数字 eD:小写数...

Micool ⋅ 2012/07/13 ⋅ 0

自己写了一个php验证码类,验证码可以正常显示,说明已经生成,但是通过属性值获取不到验证码,为空。

/* 问题:验证码可以正常显示,说明验证码已经生成(分别是$code和$gbkcode),但是通过属性值获取不到验证码,为空。 return $this->code; 为空? 求解............. */...

刘伟伟 ⋅ 2012/07/27 ⋅ 2

动态 Web 校验码图片生成--XVcode

XVcode,Web 动态验证码图片生成工具,用于生成随机验证码图片及返回验证码。以随机圆圈为干扰背景,增加随机前后景透明度,并提供3种gif动态图。 PngGenerator : GifGenerator: Gif2Generat...

PoRui ⋅ 2016/10/18 ⋅ 4

【代码实现】PHP生成各种随机验证码

文章来源:PHP开发学习门户 (自行开发的个人网站) 验证码在WEB应用中非常重要,通常用来防止用户恶意提交表单,如恶意注册和登录、论坛恶意灌水等。本文将通过实例讲解使用PHP生成各种常见...

PHP开发学习门户 ⋅ 2014/10/07 ⋅ 0

Minho/php-captcha

php-captcha 简单的php验证码库。 PHP生成验证码图片 PHP生成验证码的原理:使用PHP的GD库,生成一张带验证码的图片,并将验证码保存在Session中。PHP生成验证码的大致流程有: 1、产生一张p...

Minho ⋅ 2017/01/15 ⋅ 0

如何防止用户论坛恶意灌水

今天论坛有很多广告信息。每个版块都有几百条信息。手动发不可能。一定是用程序发的。无法通过程序判断是否灌水,只能通过设置发帖间隔时间、发帖最少字数及发帖验证码来减少。例如后台数据库...

mickelfeng ⋅ 2013/07/22 ⋅ 6

本地生成验证码

swift本地生成验证码 先上效果图 1.创建工程,新建一个继承UIView的类 2.重写init方法,实现初始化的时候调用changeVerifyCode()方法,产生随机验证码. 3.重写touchesBegan方法,实现点击切换验证...

樱黯雨 ⋅ 2016/07/20 ⋅ 0

ASP.NET 生成随机验证码

我一直觉得用第三方控件生成的验证码太花了,用户体验不好,有的很难看清楚到底是什么,还是那种比较清楚一点的给人的感觉好点。 /// /// 这个方法用来生成随机验证码 /// private void Sho...

allen_chen_0118 ⋅ 2010/06/24 ⋅ 0

PHP生成Gif图片验证码

验证码在好多地方都要用到,这里提供一个新开发的安全验证码类,支持生成Gif图片验证码(带噪点,干扰线,网格,随机色背景,随机自定义字体,倾斜,Gif动画)。从中还可以学到如何用PHP生成G...

夏日晚晴天 ⋅ 2013/10/28 ⋅ 1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

IDEA PermGen space内存溢出

解决方案: File -> Settings -> Build, Execution, Deployment / Build Tools / Maven / Runner下,找到VM Options选项,默认是空的,改为如下内容(或更大值)...

快乐的小火柴 ⋅ 7分钟前 ⋅ 0

前端常见跨域解决方案

什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。 广义的跨域: 1.) 资源跳转: A链接、重定向、表单提交2.) 资源嵌入: <link>、<script>、<im...

临江仙卜算子 ⋅ 8分钟前 ⋅ 0

系统管理命令service

service命令用来控制系统服务的实用工具,例如启动、停止、重启和关闭系统服务,以及当前状态。当然也可以直接操作,例如/etc/init.d/mysqld restart等。 语法 service (选项)(参数) 选项...

Jpchina ⋅ 13分钟前 ⋅ 0

MySQL 联合索引的命中规则

为什么要用联合索引? 对于查询语句“SELECT T.* FROM T WHERE T.c1=1 AND T.c3=2”涉及到两列,这个时候我们一般采用一个联合索引(c1, c3);而不用两个单列索引,这是因为一条查询语句往往应...

hensemlee ⋅ 20分钟前 ⋅ 0

Spring 自动组件扫描

通常情况下都是在XML配置文件中手动声明Bean和组件的。不过Spring也可以自动扫描组件实例化Bean,这样就可以避免在XML文件中繁琐的Bean声明。 手动声明Bean: 这里不再啰嗦,就是简单地在XML...

霍淇滨 ⋅ 25分钟前 ⋅ 0

MapReduce简单需求分析-共同好友及查找互粉的情况

MapReduce的设计,最重要的是要找准key,然后制定一系列的数据处理流程。MapReduce的Map中,会把key相同的分配到同一个reduce中,对于key的选择,可以找到某个相同的因素。以下面的几个例子说...

Jason_typ ⋅ 27分钟前 ⋅ 0

springboot多数据源自动切换

SpringBoot多数据源切换,先上配置文件: 1.pom: <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20......

JackyRiver ⋅ 29分钟前 ⋅ 0

Boost库编译应用

版本:Boost 1.66.0 Windows库编译 官网指南:直接执行bootstrap.bat处理文件即可,可以我却遇到一堆的问题。 环境:Windows 10 + Visual Studio 2017 Boost编译出来库命名 boost库生成文件命...

水海云 ⋅ 33分钟前 ⋅ 0

解决Eclipse发布到Tomcat丢失依赖jar包的问题

如果jar文件是以外部依赖的形式导入的。Eclipse将web项目发布到Tomcat时,是不会自动发布这些依赖的。 可以通过Eclipse在项目上右击 - Propertics - Deployment Assembly,添加“Java Build ...

ArlenXu ⋅ 33分钟前 ⋅ 0

iview tree组件层级过多时可左右滚动

使用vue+iview的tree组件,iview官网iview的tree树形控件 问题描述:tree层级过多时左右不可滚动 问题解决:修改overflow属性值 .el-tree-node>.el-tree-node_children { overflow: vi...

YXMBetter ⋅ 35分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部