文档章节

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

letwang
 letwang
发布于 2013/12/30 13:22
字数 990
阅读 613
收藏 7
<?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
粉丝 140
博文 66
码字总数 74230
作品 0
南京
技术主管
加载中

评论(2)

letwang
letwang

引用来自“kuaiyan312”的评论

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

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

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

晨曦之光
2012/03/09
186
0
自己写了一个php验证码类,验证码可以正常显示,说明已经生成,但是通过属性值获取不到验证码,为空。

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

刘伟伟
2012/07/27
1K
2
PHP生成验证码--Micoolcoder

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

Micool
2012/07/13
3.1K
0
动态 Web 校验码图片生成--XVcode

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

PoRui
2016/10/18
3.1K
4
Windows 8应用实例解析 - WinRT下创建GIF动画(Flipflop)

在Windows Store中下载了一个有意思的应用,叫做Flipflop(http://apps.microsoft.com/windows/app/flipflop/99c01512-fe4f-4d1a-872e-eb9fd6638ff4),该应用允许用户创建翻页式动画效果(Flip...

冷秋寒
06/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

阿里云API网关使用教程

API 网关(API Gateway)提供高性能、高可用的 API 托管服务,帮助用户对外开放其部署在 ECS、容器服务等阿里云产品上的应用,提供完整的 API 发布、管理、维护生命周期管理。用户只需进行简...

mcy0425
38分钟前
4
0
解决远程登陆误按ctrl+s锁屏假死恢复

使用putty时,偶尔发生屏幕假死,不能输入等情况。 后来发现,只要数据ctrl+s,就会假死;输入ctrl+q就可以恢复过来。 很多刚从windows转移到linux上来工作的朋友,在用vi/vim编辑文件时,常常...

HJCui
41分钟前
0
0
@Transactional

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于...

asdf08442a
45分钟前
2
0
widows下强制解除8080端口占用问题

使用win+R打开命令窗口 输入以下命令查看哪个任务占用了8080端口 netstat -ano |findstr "8080" 然后通过任务id强制关闭占用该端口的进程 tskill 10044 // 自己的试情况而定,这个ID是LISTE...

_Artisan
54分钟前
2
0
productFlavors简单实用

最近项目中,不同环境需要配置的参数越来越多,为了减少修改代码次数。研究了一下productFlavors的使用方式,总结如下 1. as3.0以上版本使用productFlavors时需要指定一个flavorDimensions,...

火云
57分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部